From a654d08c3bbde3e7b31920a08a30e18d1c653c32 Mon Sep 17 00:00:00 2001 From: nhmall Date: Sun, 25 May 2025 20:38:17 -0400 Subject: [PATCH] save/restore changes - part 3 This is the third of a series of savefile-related changes. This adds early-days experimental support for a completely optional 'sfctool' utility (savefile conversion tool), to be able to export a savefile's contents into a more portable format. There are likely to be bugs at this stage. In this initial first-attempt, the export format is a very simple ascii output. NetHack can be built entirely, without also building this tool. NetHack has no dependencies on the tool. Attempts were made to minimize duplication of existing NetHack code. To achieve that, unfortunately, #ifdef SFCTOOL and #ifndef SFCTOOL had to be sprinkled around through some of the existing NetHack source code, so that it could be re-used for building the utility. The process for building the sfctool typically recompiles the source files with #define SFCTOOL and a distinct object file with SF- is produced. sfctool notes: Universal ctags is used and required to produce the sfctool utility. Some targets were added to the Unix and Windows Makefiles to facilitate the build process. make sfctool That should build a copy in util. Note: At present, the Unix Makefiles do not copy sfctool over to the NetHack playground during 'make install' or 'make update'. Until that gets resolved by someone, The tool will have to be manually copied there by the builder/admin if desired. cp util/sfctool ~/nh/install/games/lib/nethackdir/sfctool Also, a separate Visual Studio sfctool.sln solution was written and placed in sys/windows/vs. That has has only very limited testing. Usage: i) To convert an existing savefile to an exportascii format that co-resides with the savefile: sfctool -c savefile That *must* be executed on the same platform / architecture / data model that produced the save file in the first place. ii) To unconvert an existing exportascii format export file to a historical format savefile that can then be used by NetHack: sfctool -u savefile That must be executed on the same target platform / architecture / data model that was used to build the NetHack that will utilize the save file that results. A Windows example: sfctool -c Fred.NetHack-saved-game That should result in creation of Fred.NetHack-saved-game.exportascii from existing savefile: %USERPROFILE%\AppData\Local\NetHack\3.7\Fred.NetHack-saved-game A Unix example: sfctool -c 1000wizard That should result in creation of 1000wizard.exportascii.gz from existing savefile in the playground save directory: 1000wizard.gz Current Mechanics: 1. Makefile recipe, or script uses universal ctags to produce util/sf.tags. 2. util/sftags is built and executed to read util/sf.tags and generate: include/sfproto.h and src/sfdata.c. 3. util/sfctool is built from the following: generated file compiled with -DSFCTOOL: src/sfdata.c -> sfdata.o existing files compiled with -DSFCTOOL: util/sfctool.c -> sfctool.o util/sfexpasc.c -> sfexpasc.o src/alloc.c -> sf-alloc.o src/monst.c -> sf-monst.o src/objects.c -> sf-objects.o src/sfbase.c -> sfbase.o src/sfstruct.c -> sfstruct.o src/nhlua.c -> sf-nhlua.o util/panic.c -> panic.o src/date.c -> sf-date.o src/decl.c -> sf-decl.o src/artifact.c -> sf-artifact.o src/dungeon.c -> sf-dungeon.o src/end.c -> sf-end.o src/engrave.c -> sf-engrave.o src/cfgfiles.c -> sf-cfgfiles.o src/files.c -> sf-files.o src/light.c -> sf-light.o src/mdlib.c -> sf-mdlib.o src/mkmaze.c -> sf-mkmaze.o src/mkroom.c -> sf-mkroom.o src/o_init.c -> sf-o_init.o src/region.c -> sf-region.o src/restore.c -> sf-restore.o src/rumors.c -> sf-rumors.o src/sys.c -> sf-sys.o src/timeout.c -> sf-timeout.o src/track.c -> sf-track.o src/version.c -> sf-version.o src/worm.c -> sf-worm.o src/strutil.c -> strutil.o --- README | 9 +- include/.gitignore | 2 + include/extern.h | 13 +- include/global.h | 5 +- include/hack.h | 14 +- include/savefile.h | 6 +- include/sfprocs.h | 13 +- src/artifact.c | 13 + src/bones.c | 9 + src/cfgfiles.c | 88 +- src/dungeon.c | 15 +- src/end.c | 4 + src/engrave.c | 6 +- src/files.c | 263 ++- src/light.c | 5 +- src/mdlib.c | 11 +- src/mkmaze.c | 13 + src/mkroom.c | 6 + src/nhlua.c | 24 +- src/o_init.c | 9 + src/region.c | 10 + src/restore.c | 139 +- src/rumors.c | 4 + src/save.c | 9 +- src/sfbase.c | 1126 ++++++++- src/sfstruct.c | 64 +- src/timeout.c | 6 + src/track.c | 2 + src/version.c | 92 +- src/worm.c | 6 + sys/unix/Makefile.top | 5 + sys/unix/Makefile.utl | 166 ++ sys/unix/hints/include/cross-post.370 | 1 + sys/unix/hints/include/cross-pre2.370 | 1 + sys/windows/Makefile.nmake | 219 +- sys/windows/vs/NetHack/NetHack.vcxproj | 2 +- sys/windows/vs/NetHackW/NetHackW.vcxproj | 2 +- sys/windows/vs/dirs.props | 2 + sys/windows/vs/fetchctags/fetchctags.nmake | 49 + sys/windows/vs/fetchctags/fetchctags.vcxproj | 71 + sys/windows/vs/sfctool.sln | 58 + sys/windows/vs/sfctool/sfctool.vcxproj | 193 ++ sys/windows/vs/sftags/aftersftags.proj | 48 + sys/windows/vs/sftags/sftags.vcxproj | 156 ++ sys/windows/windsys.c | 22 +- util/.gitignore | 5 +- util/sfctool.c | 1323 +++++++++++ util/sfexpasc.c | 1296 ++++++++++ util/sftags.c | 2230 ++++++++++++++++++ 49 files changed, 7578 insertions(+), 257 deletions(-) create mode 100644 sys/windows/vs/fetchctags/fetchctags.nmake create mode 100644 sys/windows/vs/fetchctags/fetchctags.vcxproj create mode 100644 sys/windows/vs/sfctool.sln create mode 100644 sys/windows/vs/sfctool/sfctool.vcxproj create mode 100644 sys/windows/vs/sftags/aftersftags.proj create mode 100644 sys/windows/vs/sftags/sftags.vcxproj create mode 100644 util/sfctool.c create mode 100644 util/sfexpasc.c create mode 100644 util/sftags.c diff --git a/README b/README index c3d975981..9a4923d03 100644 --- a/README +++ b/README @@ -57,10 +57,11 @@ considered spoilers: level once that square's location becomes known (found or magic mapped); goes away once sanctum temple is found (entered or high altar mapped) - - savefile: add support to deconstruct internal data structures down into - their individual fields and save those fields instead of the entire - struct - - savefile: use little-endian format for fields where that makes a difference + - savefile: add support for a tool to deconstruct data structures, + that get stored in a savefile, down into their individual fields and + save those individual fields instead of the entire struct. The + intention is to provide a way to export and transport savefiles + between platforms, architectures and data models. - - - - - - - - - - - diff --git a/include/.gitignore b/include/.gitignore index 1930f4302..6f4a4f802 100644 --- a/include/.gitignore +++ b/include/.gitignore @@ -15,3 +15,5 @@ tile.h win32api.h # really obsolete... .cvsignore +sfproto.h + diff --git a/include/extern.h b/include/extern.h index 42e47a3d4..b3e2c0949 100644 --- a/include/extern.h +++ b/include/extern.h @@ -1068,6 +1068,10 @@ extern char **get_saved_games(void); extern void free_saved_games(char **); extern void nh_compress(const char *); extern void nh_uncompress(const char *); +extern void nh_sfconvert(const char *); +extern void nh_sfunconvert(const char *); +extern int delete_convertedfile(const char *); +extern void free_convert_filenames(void); extern boolean lock_file(const char *, int, int) NONNULLARG1; extern void unlock_file(const char *) NONNULLARG1; extern void check_recordfile(const char *); @@ -1093,6 +1097,7 @@ extern boolean read_tribute(const char *, const char *, int, char *, int, extern boolean Death_quote(char *, int) NONNULLARG1; extern void livelog_add(long ll_type, const char *) NONNULLARG2; ATTRNORETURN extern void do_deferred_showpaths(int) NORETURN; +extern boolean contains_directory(const char *); /* ### fountain.c ### */ @@ -1969,7 +1974,7 @@ extern int dosuspend(void); extern void nt_regularize(char *); extern int(*nt_kbhit)(void); extern void Delay(int); -extern boolean contains_directory(const char *); +boolean get_user_home_folder(char *, size_t); # ifdef CRASHREPORT struct CRctxt; extern struct CRctxt *ctxp; @@ -2678,6 +2683,12 @@ extern boolean lookup_id_mapping(unsigned, unsigned *) NONNULLARG2; /* extern void reset_restpref(void); */ /* extern void set_restpref(const char *); */ /* extern void set_savepref(const char *); */ +#ifdef SFCTOOL +void rest_bubbles(NHFILE *); +void restore_gamelog(NHFILE *); +boolean restgamestate(NHFILE *); +void restore_msghistory(NHFILE *); +#endif /* ### rip.c ### */ diff --git a/include/global.h b/include/global.h index 727929d09..6d785ac9a 100644 --- a/include/global.h +++ b/include/global.h @@ -429,6 +429,7 @@ extern struct nomakedefs_s nomakedefs; /* PANICTRACE: Always defined for NH_DEVEL_STATUS != NH_STATUS_RELEASED but only for supported platforms. */ +#ifndef NOPANICTRACE #ifdef UNIX #if (NH_DEVEL_STATUS != NH_STATUS_RELEASED) /* see end.c */ @@ -439,6 +440,7 @@ extern struct nomakedefs_s nomakedefs; #endif /* CROSS_TO_WASM | CROSS_TO_MSDOS */ #endif /* NH_DEVEL_STATUS != NH_STATUS_RELEASED */ #endif /* UNIX */ +#endif /* !NOPANICTRACE */ /* The following are meaningless if PANICTRACE is not defined: */ #if defined(__linux__) && defined(__GLIBC__) && (__GLIBC__ >= 2) @@ -569,5 +571,6 @@ typedef enum NHL_pcall_action { NHLpa_impossible } NHL_pcall_action; -#define SFCTOOL_BIT (1UL << 30) /* needed for upcoming savefile handling */ +#define SFCTOOL_BIT (1UL << 30) + #endif /* GLOBAL_H */ diff --git a/include/hack.h b/include/hack.h index 9960d223e..fcb669d10 100644 --- a/include/hack.h +++ b/include/hack.h @@ -954,9 +954,9 @@ struct xlock_s { #define NHF_BONESFILE 3 /* modes */ #define READING 0x0 -#define COUNTING 0x1 -#define WRITING 0x2 -#define FREEING 0x4 +#define COUNTING 0x01 +#define WRITING 0x02 +#define FREEING 0x04 #define CONVERTING 0x08 #define UNCONVERTING 0x10 #if 0 @@ -972,7 +972,7 @@ struct xlock_s { enum saveformats { invalid = 0, historical = 1, /* entire struct, binary, as-is */ - cnvascii = 2, /* each field, ascii text */ + exportascii = 2, /* each field written out as ascii text */ NUM_SAVEFORMATS }; @@ -984,11 +984,11 @@ struct fieldlevel_content { struct nh_file { int fd; /* for traditional structlevel binary writes */ - int mode; /* holds READING, WRITING, or FREEING modes */ + int mode; /* holds READING, WRITING, FREEING, CONVERTING modes */ int ftype; /* NHF_LEVELFILE, NHF_SAVEFILE, or NHF_BONESFILE */ int fnidx; /* index of procs for fieldlevel saves */ - long count; /* holds current line count for default style file, - field count for binary style */ + long rcount, /* read count since opening */ + wcount; /* write count since opening */ boolean structlevel; /* traditional structure binary saves */ boolean fieldlevel; /* fieldlevel saves each field individually */ boolean addinfo; /* if set, some additional context info from core */ diff --git a/include/savefile.h b/include/savefile.h index 28cd24b23..8a4c51cf3 100644 --- a/include/savefile.h +++ b/include/savefile.h @@ -23,7 +23,7 @@ extern void sfo_uint32(NHFILE *, uint32 *, const char *); extern void sfo_uint64(NHFILE *, uint64 *, const char *); extern void sfo_size_t(NHFILE *, size_t *, const char *); extern void sfo_time_t(NHFILE *, time_t *, const char *); - +//extern void sfo_str(NHFILE *, char *, const char *, int); extern void sfo_arti_info(NHFILE *nhfp, struct arti_info *d_arti_info, const char *myname); @@ -199,7 +199,7 @@ extern void sfi_ulong(NHFILE *, ulong *, const char *); #define Sfo_uint64(a,b,c) sfo_uint64(a, b, c) #define Sfo_size_t(a,b,c) sfo_size_t(a, b, c) #define Sfo_time_t(a,b,c) sfo_time_t(a, b, c) - +#define Sfo_str(a,b,c) sfo_str(a, b, c) #define Sfo_arti_info(a,b,c) sfo_arti_info(a, b, c) #define Sfo_dgn_topology(a,b,c) sfo_dgn_topology(a, b, c) #define Sfo_dungeon(a,b,c) sfo_dungeon(a, b, c) @@ -471,7 +471,7 @@ extern void sfi_ulong(NHFILE *, ulong *, const char *); #define Sfo_uint64(a,b,c) sfo(a, b, c) #define Sfo_size_t(a,b,c) sfo(a, b, c) #define Sfo_time_t(a,b,c) sfo(a, b, c) - +#define Sfo_str(a,b,c) sfo(a, b, c) #define Sfo_arti_info(a,b,c) sfo(a, b, c) #define Sfo_dgn_topology(a,b,c) sfo(a, b, c) #define Sfo_dungeon(a,b,c) sfo(a, b, c) diff --git a/include/sfprocs.h b/include/sfprocs.h index 661d1a40a..f544b04c9 100644 --- a/include/sfprocs.h +++ b/include/sfprocs.h @@ -97,11 +97,11 @@ SF_PROTO_X(char, char); #undef SF_PROTO_C #undef SF_PROTO_X -#define SF_ENTRY(dtyp) \ +#define SF_ENTRY(dtyp) \ void (*sf_##dtyp)(NHFILE *, dtyp *, const char *) -#define SF_ENTRY_C(keyw, dtyp) \ +#define SF_ENTRY_C(keyw, dtyp) \ void (*sf_##dtyp)(NHFILE *, keyw dtyp *, const char *) -#define SF_ENTRY_X(xxx, dtyp) \ +#define SF_ENTRY_X(xxx, dtyp) \ void (*sf_##dtyp)(NHFILE *, xxx *, const char *, int bfsz) struct sf_procs { @@ -189,11 +189,14 @@ struct sf_fieldlevel_procs { struct sf_procs fn_x; /* called for fieldlevel */ }; extern struct sf_structlevel_procs sfoprocs[NUM_SAVEFORMATS], sfiprocs[NUM_SAVEFORMATS]; +extern void sf_setprocs(int, struct sf_structlevel_procs *, struct sf_structlevel_procs *); +extern void sf_setflprocs(int, struct sf_fieldlevel_procs *, struct sf_fieldlevel_procs *); +extern struct sf_structlevel_procs sfoprocs[NUM_SAVEFORMATS], sfiprocs[NUM_SAVEFORMATS]; extern struct sf_fieldlevel_procs sfoflprocs[NUM_SAVEFORMATS], sfiflprocs[NUM_SAVEFORMATS]; extern struct sf_structlevel_procs historical_sfo_procs; extern struct sf_structlevel_procs historical_sfi_procs; -extern struct sf_fieldlevel_procs cnv_sfo_procs; -extern struct sf_fieldlevel_procs cnv_sfi_procs; +extern struct sf_fieldlevel_procs exportascii_sfo_procs; +extern struct sf_fieldlevel_procs exportascii_sfi_procs; #endif /* SFPROCS_H */ diff --git a/src/artifact.c b/src/artifact.c index ddd254285..d180cb2fb 100644 --- a/src/artifact.c +++ b/src/artifact.c @@ -7,6 +7,8 @@ #include "artifact.h" #include "artilist.h" +#ifndef SFCTOOL + /* * Note: both artilist[] and artiexist[] have a dummy element #0, * so loops over them should normally start at #1. The primary @@ -57,6 +59,7 @@ staticfn void dispose_of_orig_obj(struct obj *); Note: this will still break if they have more than about half the number of hit points that will fit in a 15 bit integer. */ #define FATAL_DAMAGE_MODIFIER 200 +#endif /* SFCTOOL */ /* arti_info struct definition moved to artifact.h */ @@ -72,6 +75,7 @@ static xint16 artidisco[NROFARTIFACTS]; * and restored but that is done through this file so they can be local. */ +#ifndef SFCTOOL static const struct arti_info zero_artiexist = {0}; /* all bits zero */ staticfn void hack_artifacts(void); @@ -121,6 +125,8 @@ save_artifacts(NHFILE *nhfp) Sfo_xint16(nhfp, &artidisco[i], "artidisco"); } +#endif /* SFCTOOL */ + void restore_artifacts(NHFILE *nhfp) { @@ -130,9 +136,15 @@ restore_artifacts(NHFILE *nhfp) Sfi_arti_info(nhfp, &artiexist[i], "artiexist"); for (i = 0; i < NROFARTIFACTS; ++i) Sfi_short(nhfp, &artidisco[i], "artidisco"); +#ifndef SFCTOOL hack_artifacts(); /* redo non-saved special cases */ +#else + nhUse(artilist); +#endif } +#ifndef SFCTOOL + const char * artiname(int artinum) { @@ -2789,5 +2801,6 @@ permapoisoned(struct obj *obj) { return (obj && is_art(obj, ART_GRIMTOOTH)); } +#endif /* SFCTOOL */ /*artifact.c*/ diff --git a/src/bones.c b/src/bones.c index 31185dd28..922737fe1 100644 --- a/src/bones.c +++ b/src/bones.c @@ -5,6 +5,7 @@ #include "hack.h" +#ifndef SFCTOOL staticfn boolean no_bones_level(d_level *); staticfn void goodfruit(int); staticfn void resetobjs(struct obj *, boolean); @@ -622,6 +623,8 @@ savebones(int how, time_t when, struct obj *corpse) compress_bonesfile(); } +#endif /* !SFCTOOL */ + int getbones(void) { @@ -630,6 +633,7 @@ getbones(void) char c = 0, *bonesid, oldbonesid[40] = { 0 }; /* was [10]; more should be safer */ +#ifndef SFCTOOL if (discover) /* save bones files for real games */ return 0; @@ -641,6 +645,7 @@ getbones(void) return 0; if (no_bones_level(&u.uz)) return 0; +#endif /* !SFCTOOL */ nhfp = open_bonesfile(&u.uz, &bonesid); if (!nhfp) @@ -740,6 +745,8 @@ getbones(void) return ok; } +#ifndef SFCTOOL + /* check whether current level contains bones from a particular player */ boolean bones_include_name(const char *name) @@ -821,4 +828,6 @@ free_ebones(struct monst *mtmp) } } +#endif /* SFCTOOL */ + /*bones.c*/ diff --git a/src/cfgfiles.c b/src/cfgfiles.c index 52f45a7a4..9d8de7f86 100644 --- a/src/cfgfiles.c +++ b/src/cfgfiles.c @@ -35,6 +35,7 @@ staticfn char *is_config_section(char *); staticfn boolean handle_config_section(char *); boolean parse_config_line(char *); staticfn char *find_optparam(const char *); +#ifndef SFCTOOL staticfn boolean cnf_line_OPTIONS(char *); staticfn boolean cnf_line_AUTOPICKUP_EXCEPTION(char *); staticfn boolean cnf_line_BINDINGS(char *); @@ -53,6 +54,7 @@ staticfn boolean cnf_line_NAME(char *); staticfn boolean cnf_line_ROLE(char *); staticfn boolean cnf_line_dogname(char *); staticfn boolean cnf_line_catname(char *); +#endif /* SFCTOOL */ #ifdef SYSCF staticfn boolean cnf_line_WIZARDS(char *); staticfn boolean cnf_line_SHELLERS(char *); @@ -80,12 +82,12 @@ staticfn boolean cnf_line_PANICTRACE_GDB(char *); staticfn boolean cnf_line_GDBPATH(char *); staticfn boolean cnf_line_GREPPATH(char *); staticfn boolean cnf_line_CRASHREPORTURL(char *); -staticfn boolean cnf_line_SAVEFORMAT(char *); -staticfn boolean cnf_line_BONESFORMAT(char *); staticfn boolean cnf_line_ACCESSIBILITY(char *); + staticfn boolean cnf_line_PORTABLE_DEVICE_PATHS(char *); staticfn void parseformat(int *, char *); #endif /* SYSCF */ +#ifndef SFCTOOL staticfn boolean cnf_line_BOULDER(char *); staticfn boolean cnf_line_MENUCOLOR(char *); staticfn boolean cnf_line_HILITE_STATUS(char *); @@ -101,6 +103,7 @@ staticfn boolean cnf_line_QT_TILEWIDTH(char *); staticfn boolean cnf_line_QT_TILEHEIGHT(char *); staticfn boolean cnf_line_QT_FONTSIZE(char *); staticfn boolean cnf_line_QT_COMPACT(char *); +#endif /* SFCTOOL */ struct _cnf_parser_state; /* defined below (far below...) */ staticfn void cnf_parser_init(struct _cnf_parser_state *parser); staticfn void cnf_parser_done(struct _cnf_parser_state *parser); @@ -109,6 +112,13 @@ staticfn void parse_conf_buf(struct _cnf_parser_state *parser, /* next one is in extern.h; why here too? */ boolean parse_conf_str(const char *str, boolean (*proc)(char *arg)); +#ifdef SFCTOOL +#ifdef wait_synch +#undef wait_synch +#endif +#define wait_synch() +#endif /* SFCTOOL */ + /* ---------- BEGIN CONFIG FILE HANDLING ----------- */ /* used for messaging. Also used in options.c */ @@ -151,6 +161,8 @@ get_default_configfile(void) const char *backward_compat_configfile = "nethack.cnf"; #endif +#ifndef SFCTOOL + /* #saveoptions - save config options into file */ int do_write_config_file(void) @@ -195,6 +207,7 @@ do_write_config_file(void) } return ECMD_OK; } +#endif /* SFCTOOL */ /* remember the name of the file we're accessing; if may be used in option reject messages */ @@ -455,7 +468,11 @@ choose_random_part(char *str, char sep) nsep++; str++; } +#ifndef SFCTOOL csep = rn2(nsep); +#else + csep = 1; +#endif str = begin; while ((csep > 0) && *str) { str++; @@ -571,6 +588,8 @@ find_optparam(const char *buf) return bufp; } +#ifndef SFCTOOL + staticfn boolean cnf_line_OPTIONS(char *origbuf) { @@ -759,6 +778,7 @@ cnf_line_catname(char *bufp) (void) strncpy(gc.catname, bufp, PL_PSIZ - 1); return TRUE; } +#endif /* SFCTOOL */ #ifdef SYSCF @@ -1088,20 +1108,6 @@ cnf_line_CRASHREPORTURL(char *bufp) return TRUE; } -staticfn boolean -cnf_line_SAVEFORMAT(char *bufp) -{ - parseformat(sysopt.saveformat, bufp); - return TRUE; -} - -staticfn boolean -cnf_line_BONESFORMAT(char *bufp) -{ - parseformat(sysopt.bonesformat, bufp); - return TRUE; -} - staticfn boolean cnf_line_ACCESSIBILITY(char *bufp) { @@ -1135,6 +1141,8 @@ cnf_line_PORTABLE_DEVICE_PATHS(char *bufp) } #endif /* SYSCF */ +#ifndef SFCTOOL + staticfn boolean cnf_line_BOULDER(char *bufp) { @@ -1271,6 +1279,7 @@ cnf_line_QT_COMPACT(char *bufp) #endif return TRUE; } +#endif /* SFCTOOL */ typedef boolean (*config_line_stmt_func)(char *); @@ -1288,6 +1297,7 @@ static const struct match_config_line_stmt { boolean origbuf; config_line_stmt_func fn; } config_line_stmt[] = { +#ifndef SFCTOOL /* OPTIONS handled separately */ { "OPTIONS", 4, FALSE, TRUE, cnf_line_OPTIONS }, CNFL_N(AUTOPICKUP_EXCEPTION, 5), @@ -1309,6 +1319,7 @@ static const struct match_config_line_stmt { CNFL_NA(CHARACTER, 4, ROLE), CNFL_N(dogname, 3), CNFL_N(catname, 3), +#endif /* SFCTOOL */ #ifdef SYSCF CNFL_S(WIZARDS, 7), CNFL_S(SHELLERS, 8), @@ -1336,11 +1347,10 @@ static const struct match_config_line_stmt { CNFL_S(CRASHREPORTURL, 13), CNFL_S(GDBPATH, 7), CNFL_S(GREPPATH, 7), - CNFL_S(SAVEFORMAT, 10), - CNFL_S(BONESFORMAT, 11), CNFL_S(ACCESSIBILITY, 13), CNFL_S(PORTABLE_DEVICE_PATHS, 8), #endif /*SYSCF*/ +#ifndef SFCTOOL CNFL_N(BOULDER, 3), CNFL_N(MENUCOLOR, 9), CNFL_N(HILITE_STATUS, 6), @@ -1356,6 +1366,7 @@ static const struct match_config_line_stmt { CNFL_N(QT_TILEHEIGHT, 13), CNFL_N(QT_FONTSIZE, 11), CNFL_N(QT_COMPACT, 10) +#endif /* SFCTOOL */ }; #undef CNFL_N @@ -1485,6 +1496,7 @@ config_error_nextline(const char *line) return TRUE; } +#ifndef SFCTOOL int l_get_config_errors(lua_State *L) { @@ -1510,6 +1522,7 @@ l_get_config_errors(lua_State *L) return 1; } +#endif /* SFCTOOL */ /* varargs 'config_error_add()' moved to pline.c */ void @@ -1600,9 +1613,10 @@ read_config_file(const char *filename, int src) if (!(fp = fopen_config_file(filename, src))) return FALSE; - +#ifndef SFCTOOL /* begin detection of duplicate configfile options */ reset_duplicate_opt_detection(); +#endif /* SFCTOOL */ free_config_sections(); iflags.parse_config_file_src = src; @@ -1610,8 +1624,10 @@ read_config_file(const char *filename, int src) (void) fclose(fp); free_config_sections(); +#ifndef SFCTOOL /* turn off detection of duplicate configfile options */ reset_duplicate_opt_detection(); +#endif /* SFCTOOL */ return rv; } @@ -1859,38 +1875,6 @@ vconfig_error_add(const char *str, va_list the_args) } #ifdef SYSCF -staticfn void -parseformat(int *arr, char *str) -{ - const char *legal[] = { "historical", "cnv" }; - int i, kwi = 0, words = 0; - char *p = str, *keywords[2] = { NULL }; - - while (*p) { - while (*p && isspace((uchar) *p)) { - *p = '\0'; - p++; - } - if (*p) { - words++; - if (kwi < 2) - keywords[kwi++] = p; - } - while (*p && !isspace((uchar) *p)) - p++; - } - if (!words) { - impossible("missing format list"); - return; - } - while (--kwi >= 0) - if (kwi < 2) { - for (i = 0; i < SIZE(legal); ++i) { - if (!strcmpi(keywords[kwi], legal[i])) - arr[kwi] = i + 1; - } - } -} #ifdef SYSCF_FILE void assure_syscf_file(void) @@ -1924,8 +1908,10 @@ assure_syscf_file(void) close(fd); return; } +#ifndef SFCTOOL if (gd.deferred_showpaths) do_deferred_showpaths(1); /* does not return */ +#endif raw_printf("Unable to open SYSCF_FILE.\n"); exit(EXIT_FAILURE); } diff --git a/src/dungeon.c b/src/dungeon.c index cbc2abd8f..c3d9b8e43 100644 --- a/src/dungeon.c +++ b/src/dungeon.c @@ -34,6 +34,7 @@ struct lchoice { static mapseen *load_mapseen(NHFILE *); +#ifndef SFCTOOL #if 0 staticfn void Fread(genericptr_t, int, int, dlb *); #endif @@ -202,6 +203,7 @@ save_dungeon( svm.mapseenchn = 0; } } +#endif /* !SFCTOOL */ /* Restore the dungeon structures. */ void @@ -259,6 +261,7 @@ restore_dungeon(NHFILE *nhfp) } } +#ifndef SFCTOOL #if 0 staticfn void Fread(genericptr_t ptr, int size, int nitems, dlb *stream) @@ -1428,6 +1431,7 @@ depth(d_level *lev) { return (schar) (svd.dungeons[lev->dnum].depth_start + lev->dlevel - 1); } +#endif /* !SFCTOOL */ /* are "lev1" and "lev2" actually the same? */ boolean @@ -1437,6 +1441,7 @@ on_level(d_level *lev1, d_level *lev2) && lev1->dlevel == lev2->dlevel); } +#ifndef SFCTOOL /* is this level referenced in the special level chain? */ s_level * Is_special(d_level *lev) @@ -1602,6 +1607,8 @@ u_on_rndspot(int upflag) switch_terrain(); } +#endif /* !SFCTOOL */ +#ifndef SFCTOOL boolean Is_botlevel(d_level *lev) { @@ -2536,6 +2543,7 @@ donamelevel(void) query_annotation((d_level *) 0); return ECMD_OK; } +#endif /* !SFCTOOL */ /* exclusion zones */ void @@ -2562,7 +2570,7 @@ save_exclusions(NHFILE *nhfp) ; if (update_file(nhfp)) { - Sfo_int(nhfp, &nez, "exclusion-count"); + Sfo_int(nhfp, &nez, "exclusion_count"); for (ez = sve.exclusion_zones; ez; ez = ez->next) { Sfo_xint16(nhfp, &ez->zonetype, "exclusion-zonetype"); Sfo_coordxy(nhfp, &ez->lx, "exclusion-lx"); @@ -2593,6 +2601,8 @@ load_exclusions(NHFILE *nhfp) } } +#ifndef SFCTOOL + /* find the particular mapseen object in the chain; may return null */ staticfn mapseen * find_mapseen(d_level *lev) @@ -2673,6 +2683,7 @@ save_mapseen(NHFILE *nhfp, mapseen *mptr) } savecemetery(nhfp, &mptr->final_resting_place); } +#endif /* !SFCTOOL */ staticfn mapseen * load_mapseen(NHFILE *nhfp) @@ -2709,6 +2720,7 @@ load_mapseen(NHFILE *nhfp) restcemetery(nhfp, &load->final_resting_place); return load; } +#ifndef SFCTOOL DISABLE_WARNING_FORMAT_NONLITERAL @@ -3682,6 +3694,7 @@ print_mapseen( } } } +#endif /* !SFCTOOL */ #undef OF_INTEREST #undef ADDNTOBUF #undef ADDTOBUF diff --git a/src/end.c b/src/end.c index e17c17517..ba2ea4f19 100644 --- a/src/end.c +++ b/src/end.c @@ -14,6 +14,7 @@ #endif #include "dlb.h" +#ifndef SFCTOOL #ifndef NO_SIGNAL staticfn void done_intr(int); # if defined(UNIX) || defined(VMS) || defined(__EMX__) @@ -33,9 +34,11 @@ staticfn void dump_plines(void); #endif staticfn void dump_everything(int, time_t); staticfn void fixup_death(int); +#endif /* SFCTOOL */ staticfn int wordcount(char *); staticfn void bel_copy1(char **, char *); +#ifndef SFCTOOL #define done_stopprint program_state.stopprint /* @@ -1767,6 +1770,7 @@ save_killers(NHFILE *nhfp) } } } +#endif /* !SFCTOOL */ void restore_killers(NHFILE *nhfp) diff --git a/src/engrave.c b/src/engrave.c index 00602e0fc..9d598e341 100644 --- a/src/engrave.c +++ b/src/engrave.c @@ -37,7 +37,7 @@ struct _doengrave_ctx { size_t len; /* # of nonspace chars of new engraving text */ }; - +#ifndef SFCTOOL staticfn int stylus_ok(struct obj *); staticfn boolean u_can_engrave(void); staticfn void doengrave_ctx_init(struct _doengrave_ctx *); @@ -1542,6 +1542,7 @@ save_engravings(NHFILE *nhfp) if (release_data(nhfp)) head_engr = 0; } +#endif /* !SFCTOOL */ void rest_engravings(NHFILE *nhfp) @@ -1581,6 +1582,7 @@ rest_engravings(NHFILE *nhfp) } } +#ifndef SFCTOOL DISABLE_WARNING_FORMAT_NONLITERAL /* to support '#stats' wizard-mode command */ @@ -1728,5 +1730,5 @@ blengr(void) { return ROLL_FROM(blind_writing); } - +#endif /* !SFCTOOL */ /*engrave.c*/ diff --git a/src/files.c b/src/files.c index 238d03662..821b1cff8 100644 --- a/src/files.c +++ b/src/files.c @@ -12,6 +12,28 @@ #include "hack.h" #include "dlb.h" +#ifdef SFCTOOL +#ifdef TTY_GRAPHICS +#undef TTY_GRAPHICS +#endif +#ifdef mark_synch +#undef mark_synch +#endif +#define mark_synch() +#ifdef raw_print +#undef raw_print +#endif +#define raw_print(a) +#ifdef WINDOWPORT +#undef WINDOWPORT +#endif +#define WINDOWPORT(x) FALSE +#ifdef clear_nhwindow +#undef clear_nhwindow +#endif +#define clear_nhwindow(x) +#endif /* SFCTOOL */ + #ifdef TTY_GRAPHICS #include "wintty.h" /* more() */ #endif @@ -125,8 +147,13 @@ extern boolean get_user_home_folder(char *, size_t); #define PRAGMA_UNUSED #endif +#ifndef SFCTOOL staticfn NHFILE *new_nhfile(void); staticfn void free_nhfile(NHFILE *); +#else +NHFILE *new_nhfile(void); +void free_nhfile(NHFILE *); +#endif /* SFCTOOL */ #ifdef SELECTSAVED staticfn int QSORTCALLBACK strcmp_wrap(const void *, const void *); @@ -144,6 +171,12 @@ staticfn boolean make_compressed_name(const char *, char *); #endif staticfn NHFILE *problematic_savefile(int, const char *); +#ifndef SFCTOOL +staticfn int doconvert_file(const char *, int, boolean); +#endif /* SFCTOOL */ +staticfn boolean make_converted_name(const char *); + +#ifndef SFCTOOL staticfn NHFILE *viable_nhfile(NHFILE *); #ifdef SELECTSAVED staticfn int QSORTCALLBACK strcmp_wrap(const void *, const void *); @@ -159,6 +192,7 @@ boolean proc_wizkit_line(char *buf); void read_wizkit(void); /* in extern.h; why here too? */ staticfn FILE *fopen_sym_file(void); staticfn NHFILE *viable_nhfile(NHFILE *); +#endif /* !SFCTOOL */ /* return a file's name without its path and optionally trailing 'type' */ const char * @@ -354,6 +388,7 @@ fqname(const char *basenam, #endif /* !PREFIXES_IN_USE */ } +#ifndef SFCTOOL /* reasonbuf must be at least BUFSZ, supplied by caller */ int validate_prefix_locations(char *reasonbuf) @@ -414,6 +449,7 @@ fopen_datafile(const char *filename, const char *mode, int prefix) fp = fopen(filename, mode); return fp; } +#endif /* !SFCTOOL */ /* ---------- EXTERNAL FILE SUPPORT ----------- */ @@ -433,7 +469,7 @@ zero_nhfile(NHFILE *nhfp) nhfp->fpdef = (FILE *) 0; nhfp->fplog = (FILE *) 0; nhfp->fpdebug = (FILE *) 0; - nhfp->count = 0; + nhfp->rcount = nhfp->wcount = 0; nhfp->eof = FALSE; nhfp->fnidx = 0; nhfp->style.deflt = FALSE; @@ -441,7 +477,10 @@ zero_nhfile(NHFILE *nhfp) nhfp->nhfpconvert = 0; } -staticfn NHFILE * +#ifndef SFCTOOL +staticfn +#endif +NHFILE * new_nhfile(void) { NHFILE *nhfp = (NHFILE *) alloc(sizeof(NHFILE)); @@ -450,7 +489,10 @@ new_nhfile(void) return nhfp; } -staticfn void +#ifndef SFCTOOL +staticfn +#endif +void free_nhfile(NHFILE *nhfp) { if (nhfp) { @@ -477,13 +519,18 @@ close_nhfile(NHFILE *nhfp) void rewind_nhfile(NHFILE *nhfp) { + if (nhfp->structlevel) { #ifdef BSD - (void) lseek(nhfp->fd, 0L, 0); + (void) lseek(nhfp->fd, 0L, 0); #else - (void) lseek(nhfp->fd, (off_t) 0, 0); + (void) lseek(nhfp->fd, (off_t) 0, 0); #endif + } else { + rewind(nhfp->fpdef); + } } +#ifndef SFCTOOL staticfn NHFILE * viable_nhfile(NHFILE *nhfp) { @@ -517,6 +564,7 @@ viable_nhfile(NHFILE *nhfp) } return nhfp; } +#endif /* !SFCTOOL */ int nhclose(int fd) @@ -534,6 +582,7 @@ nhclose(int fd) /* ---------- BEGIN LEVEL FILE HANDLING ----------- */ +#ifndef SFCTOOL /* Construct a file name for a level-type file, which is of the form * something.level (with any old level stripped off). * This assumes there is space on the end of 'file' to append @@ -881,7 +930,7 @@ open_bonesfile(d_level *lev, char **bonesid) nhfp->mode = READING; nhfp->addinfo = TRUE; nhfp->style.deflt = TRUE; - nhfp->style.binary = (sysopt.bonesformat[0] != cnvascii); + nhfp->style.binary = (sysopt.bonesformat[0] != exportascii); nhfp->fnidx = sysopt.bonesformat[0]; nhfp->fd = -1; nhfp->fpdef = fopen(fq_bones, nhfp->style.binary ? RDBMODE : RDTMODE); @@ -912,6 +961,7 @@ delete_bonesfile(d_level *lev) (void) set_bonesfile_name(gb.bones, lev); reslt = unlink(fqname(gb.bones, BONESPREFIX, 0)); + delete_convertedfile(fqname(gb.bones, BONESPREFIX, 0)); return !(reslt < 0); } @@ -920,8 +970,10 @@ delete_bonesfile(d_level *lev) void compress_bonesfile(void) { + nh_sfconvert(fqname(gb.bones, BONESPREFIX, 0)); nh_compress(fqname(gb.bones, BONESPREFIX, 0)); } +#endif /* !SFCTOOL */ /* ---------- END BONES FILE HANDLING ----------- */ @@ -1035,6 +1087,7 @@ set_savefile_name(boolean regularize_it) #endif } +#ifndef SFCTOOL #ifdef INSURANCE void save_savefile_name(NHFILE *nhfp) @@ -1172,6 +1225,7 @@ delete_savefile(void) const char *sfname = fqname(gs.SAVEF, SAVEPREFIX, 0); (void) unlink(sfname); + (void) delete_convertedfile(sfname); return 0; /* for restore_saved_game() (ex-xxxmain.c) test */ } @@ -1439,6 +1493,7 @@ free_saved_games(char **saved) free((genericptr_t) saved); } } +#endif /* !SFCTOOL */ /* ---------- END SAVE FILE HANDLING ----------- */ @@ -1490,13 +1545,20 @@ docompress_file(const char *filename, boolean uncomp) #ifdef TTY_GRAPHICS boolean istty = WINDOWPORT(tty); #endif + #ifdef COMPRESS_EXTENSION xtra = COMPRESS_EXTENSION; #else xtra = ""; #endif +#ifdef SFCTOOL + ln = strlen(filename) + sizeof COMPRESS_EXTENSION; + cfn = (char *) alloc(ln); +#else /* SFCTOOL */ ln = (unsigned) (strlen(filename) + strlen(xtra)); cfn = (char *) alloc(ln + 1); +#endif /* SFCTOOL */ + Strcpy(cfn, filename); Strcat(cfn, xtra); @@ -1540,8 +1602,9 @@ docompress_file(const char *filename, boolean uncomp) * there is an error message from the compression, the 'y' or 'n' can * end up being displayed after the error message. */ - if (istty) + if (istty) { mark_synch(); + } #endif f = fork(); if (f == 0) { /* child */ @@ -1551,8 +1614,9 @@ docompress_file(const char *filename, boolean uncomp) * them will have to clear the first line. This should be * invisible if there are no error messages. */ - if (istty) + if (istty) { raw_print(""); + } #endif /* run compressor without privileges, in case other programs * have surprises along the line of gzip once taking filenames @@ -1715,10 +1779,17 @@ docompress_file(const char *filename, boolean uncomp) { gzFile compressedfile; FILE *uncompressedfile; +#ifndef SFCTOOL char cfn[256]; +#else + char *cfn; +#endif char buf[1024]; unsigned len, len2; +#ifdef SFCTOOL + cfn = (char *) alloc(strlen(filename) + strlen(COMPRESS_EXTENSION) + 1); +#endif if (!make_compressed_name(filename, cfn)) return; @@ -1739,6 +1810,9 @@ docompress_file(const char *filename, boolean uncomp) } else { panic("Error in docompress_file %d", errno); } +#ifdef SFCTOOL + free(cfn); +#endif fclose(uncompressedfile); return; } @@ -1753,6 +1827,9 @@ docompress_file(const char *filename, boolean uncomp) fclose(uncompressedfile); gzclose(compressedfile); (void) unlink(cfn); +#ifdef SFCTOOL + free(cfn); +#endif return; } if (len == 0) @@ -1765,6 +1842,9 @@ docompress_file(const char *filename, boolean uncomp) fclose(uncompressedfile); gzclose(compressedfile); (void) unlink(cfn); +#ifdef SFCTOOL + free(cfn); +#endif return; } } @@ -1790,12 +1870,18 @@ docompress_file(const char *filename, boolean uncomp) panic("Error in zlib docompress_file %s, %d", filename, errno); } +#ifdef SFCTOOL + free(cfn); +#endif return; } uncompressedfile = fopen(filename, WRBMODE); if (!uncompressedfile) { pline("Error in zlib docompress file uncompress %s", filename); gzclose(compressedfile); +#ifdef SFCTOOL + free(cfn); +#endif return; } @@ -1809,6 +1895,9 @@ docompress_file(const char *filename, boolean uncomp) fclose(uncompressedfile); gzclose(compressedfile); (void) unlink(filename); +#ifdef SFCTOOL + free(cfn); +#endif return; } if (len == 0) @@ -1821,6 +1910,9 @@ docompress_file(const char *filename, boolean uncomp) fclose(uncompressedfile); gzclose(compressedfile); (void) unlink(filename); +#ifdef SFCTOOL + free(cfn); +#endif return; } } @@ -1831,6 +1923,9 @@ docompress_file(const char *filename, boolean uncomp) /* Delete the file left behind */ (void) unlink(cfn); } +#ifdef SFCTOOL + free(cfn); +#endif } #endif /* RLC 09 Mar 1999: End ZLIB patch */ @@ -1840,7 +1935,7 @@ docompress_file(const char *filename, boolean uncomp) /* ---------- BEGIN PROBLEMATIC SAVEFILE HANDLING ----------- */ - +#ifndef SFCTOOL static struct sfstatus_to_msg { int sfstatus; const char *msg; @@ -1873,6 +1968,8 @@ problematic_savefile(int sfstatus, const char *savefilenm) case SF_DM_ILP32LL64_ON_IL32LLP64: case SF_DM_I32LP64_ON_IL32LLP64: case SF_DM_IL32LLP64_ON_I32LP64: + FALLTHROUGH; + /*FALLTHRU*/ case SF_DM_MISMATCH: case SF_OUTDATED: case SF_CRITICAL_BYTE_COUNT_MISMATCH: @@ -1889,11 +1986,155 @@ problematic_savefile(int sfstatus, const char *savefilenm) } return nhfp; } +#endif /* !SFCTOOL */ /* ---------- END PROBLEMATIC SAVEFILE HANDLING ----------- */ +/* ---------- BEGIN EXTERNAL CONVERSION HANDLING ----------- */ + +static boolean cvtinit = FALSE; + +#ifndef SFCTOOL +static char *unconverted_filename = 0, *converted_filename = 0; + +/* + * Returns non-zero if unconvert was successful + */ +staticfn int +doconvert_file(const char *filename, int sfstatus, boolean unconvert) +{ + nhUse(sfstatus); + nhUse(unconvert); + return 1; +} + +/* convert file */ +void nh_sfconvert(const char *filename) +{ + (void) doconvert_file(filename, 0, FALSE); +} + +/* unconvert file if it exists */ +void nh_sfunconvert(const char *filename) +{ + (void) doconvert_file(filename, 0, TRUE); +} + +#else /* !SFCTOOL */ +/* in sfctool, these are in sfctool.c, not in here */ +extern char *unconverted_filename, *converted_filename; +#endif /* !SFCTOOL */ + +staticfn boolean +make_converted_name(const char *filename) +{ + unsigned ln; + const char *xtra, *finaldirchar; + const char *dir = NULL; + boolean needsep = FALSE; +#if defined(WIN32) + static char folderbuf[MAX_PATH]; +#endif + + if (!filename) + return FALSE; + + if (unconverted_filename) + free((genericptr_t) unconverted_filename), unconverted_filename = 0; + if (converted_filename) + free((genericptr_t) converted_filename), converted_filename = 0; + +#ifndef SHORT_FILENAMES + /* do we need to do some ms-dos processing here? */ +#endif /* SHORT_FILENAMES */ + + ln = (unsigned) strlen(filename); + if (!contains_directory(filename)) { +#if defined(UNIX) + dir = nh_getenv("NETHACKDIR"); + if (!dir) + dir = nh_getenv("HACKDIR"); +#ifdef HACKDIR + if (!dir) + dir = HACKDIR; +#endif +#elif defined(WIN32) + if (get_user_home_folder(folderbuf, sizeof folderbuf)) { + size_t sz = strlen(folderbuf); + + Snprintf(eos(folderbuf), sizeof folderbuf - sz, + "\\AppData\\Local\\NetHack\\3.7\\"); + dir = (const char *) folderbuf; + } +#endif /* UNIX || WIN32 */ + if (dir) { + finaldirchar = c_eos(dir); + finaldirchar--; + if (!(*finaldirchar == '/' || *finaldirchar == '\\' + || *finaldirchar == ':')) { + needsep = TRUE; + ln += 1; + } + ln += strlen(dir); + } + } + unconverted_filename = (char *) alloc(ln + 1); + Snprintf(unconverted_filename, ln + 1, "%s%s%s", + dir ? dir : "", + (dir && needsep) ? "/" : "", + filename); + xtra = ".exportascii"; + ln += (unsigned) strlen(xtra); + converted_filename = (char *) alloc(ln + 1); + Strcpy(converted_filename, unconverted_filename); + Strcat(converted_filename, xtra); + return TRUE; +} + +/* delete converted savefile as a normal course of action */ +int +delete_convertedfile(const char *basefilename) +{ + if (!converted_filename) + make_converted_name(basefilename); + if (converted_filename) { + (void) unlink(converted_filename); + } + return 0; +} + +void free_convert_filenames(void) +{ + if (converted_filename) + free((genericptr_t) converted_filename), converted_filename = 0; + if (unconverted_filename) + free((genericptr_t) unconverted_filename), unconverted_filename = 0; + cvtinit = FALSE; +} + +/* return TRUE if s contains a directory, not just a filespec */ +boolean +contains_directory(const char *s) +{ + int i, slen = strlen(s); + const char *cp = s; + + for (i = 0; i < slen; ++i) { + if (*cp == '\\' || *cp == '/' || *cp == ':') + return TRUE; + cp++; + } + return FALSE; +} + +/* =========================================================================*/ + +/* ---------- END EXTERNAL CONVERSION HANDLING ----------- */ + /* ---------- BEGIN FILE LOCKING HANDLING ----------- */ +#ifndef SFCTOOL + #if defined(NO_FILE_LINKS) || defined(USE_FCNTL) /* implies UNIX */ static int lockfd = -1; /* for lock_file() to pass to unlock_file() */ #endif @@ -2802,6 +3043,7 @@ do_deferred_showpaths(int code) #endif #endif } +#endif /* !SFCTOOL */ #ifdef DEBUG /* used by debugpline() to decide whether to issue a message @@ -2856,6 +3098,7 @@ debugcore(const char *filename, boolean wildcards) #endif /*DEBUG*/ +#ifndef SFCTOOL #ifdef UNIX #ifndef PATH_MAX #include @@ -3346,6 +3589,8 @@ Death_quote(char *buf, int bufsz) } /* ---------- END TRIBUTE ----------- */ +#endif /* !SFCTOOL */ + #ifdef LIVELOG #define LLOG_SEP "\t" /* livelog field separator, as a string literal */ #define LLOG_EOL "\n" /* end-of-line, for abstraction consistency */ diff --git a/src/light.c b/src/light.c index 618ba5684..574665fa9 100644 --- a/src/light.c +++ b/src/light.c @@ -42,6 +42,7 @@ #define LSF_NEEDS_FIXUP 0x2 /* need oid fixup */ #define LSF_IS_PROBLEMATIC 0x4 /* impossible situation encountered */ +#ifndef SFCTOOL staticfn light_source *new_light_core(coordxy, coordxy, int, int, anything *) NONNULLPTRS; staticfn void delete_ls(light_source *); @@ -468,6 +469,7 @@ save_light_sources(NHFILE *nhfp, int range) } } } +#endif /* !SFCTOOL */ /* * Pull in the structures from disk, but don't recalculate the object @@ -490,6 +492,7 @@ restore_light_sources(NHFILE *nhfp) } } +#ifndef SFCTOOL DISABLE_WARNING_FORMAT_NONLITERAL @@ -970,7 +973,7 @@ wiz_light_sources(void) return ECMD_OK; } - +#endif /* !SFCTOOL */ /* for 'onefile' processing where end of this file isn't necessarily the end of the source code seen by the compiler */ #undef LSF_SHOW diff --git a/src/mdlib.c b/src/mdlib.c index 95d4f1f2a..701b39901 100644 --- a/src/mdlib.c +++ b/src/mdlib.c @@ -61,7 +61,10 @@ char *version_id_string(char *, size_t, const char *) NONNULL NONNULLPTRS; char *bannerc_string(char *, size_t, const char *) NONNULL NONNULLPTRS; int case_insensitive_comp(const char *, const char *) NONNULLPTRS; -staticfn void make_version(void); +#ifndef SFCTOOL +staticfn +#endif /* SFCTOOL */ +void make_version(void); #ifndef HAS_NO_MKSTEMP #ifdef _MSC_VER @@ -234,10 +237,14 @@ md_ignored_features(void) { return (0UL | (1UL << 19) /* SCORE_ON_BOTL */ + | SFCTOOL_BIT /* stored by SFCTOOL, not NetHack itself */ ); } -staticfn void +#ifndef SFCTOOL +staticfn +#endif +void make_version(void) { int i; diff --git a/src/mkmaze.c b/src/mkmaze.c index af12ba15e..9c665a37e 100644 --- a/src/mkmaze.c +++ b/src/mkmaze.c @@ -6,6 +6,7 @@ #include "hack.h" #include "sp_lev.h" +#ifndef SFCTOOL staticfn int iswall(coordxy, coordxy); staticfn int iswall_or_stone(coordxy, coordxy); staticfn boolean is_solid(coordxy, coordxy); @@ -1736,6 +1737,7 @@ save_waterlevel(NHFILE *nhfp) if (release_data(nhfp)) unsetup_waterlevel(); } +#endif /* !SFCTOOL */ /* restoring air bubbles on Plane of Water or clouds on Plane of Air */ void @@ -1744,6 +1746,11 @@ restore_waterlevel(NHFILE *nhfp) struct bubble *b = (struct bubble *) 0, *btmp; int i, n = 0; +#ifdef SFCTOOL + svb.bbubbles = (struct bubble *) 0; + /* set_wportal(); */ +#endif + Sfi_int(nhfp, &n, "waterlevel-bubble_count"); Sfi_int(nhfp, &svx.xmin, "waterlevel-xmin"); Sfi_int(nhfp, &svy.ymin, "waterlevel-ymin"); @@ -1760,8 +1767,11 @@ restore_waterlevel(NHFILE *nhfp) svb.bbubbles = b; b->prev = (struct bubble *) 0; } +#ifndef SFCTOOL mv_bubble(b, 0, 0, TRUE); +#endif } +#ifndef SFCTOOL ge.ebubbles = b; if (b) { b->next = (struct bubble *) 0; @@ -1778,8 +1788,10 @@ restore_waterlevel(NHFILE *nhfp) : "air bubbles or clouds"); program_state.something_worth_saving = 1; } +#endif } +#ifndef SFCTOOL staticfn void set_wportal(void) { @@ -2087,5 +2099,6 @@ mv_bubble(struct bubble *b, coordxy dx, coordxy dy, boolean ini) } } } +#endif /* !SFCTOOL */ /*mkmaze.c*/ diff --git a/src/mkroom.c b/src/mkroom.c index 21dd56912..c859b1c0e 100644 --- a/src/mkroom.c +++ b/src/mkroom.c @@ -17,6 +17,7 @@ #include "hack.h" +#ifndef SFCTOOL staticfn boolean isbig(struct mkroom *); staticfn struct mkroom *pick_room(boolean); staticfn void mkshop(void), mkzoo(int), mkswamp(void); @@ -25,10 +26,12 @@ staticfn void mktemple(void); staticfn coord *shrine_pos(int); staticfn struct permonst *morguemon(void); staticfn struct permonst *squadmon(void); +#endif /* SFCTOOL */ staticfn void save_room(NHFILE *, struct mkroom *); staticfn void rest_room(NHFILE *, struct mkroom *); +#ifndef SFCTOOL staticfn boolean invalid_shop_shape(struct mkroom *sroom); #define sq(x) ((x) * (x)) @@ -866,6 +869,7 @@ save_rooms(NHFILE *nhfp) for (i = 0; i < svn.nroom; i++) save_room(nhfp, &svr.rooms[i]); } +#endif /* !SFCTOOL */ staticfn void rest_room(NHFILE *nhfp, struct mkroom *r) @@ -901,6 +905,7 @@ rest_rooms(NHFILE *nhfp) gs.subrooms[gn.nsubroom].hx = -1; } +#ifndef SFCTOOL /* convert a display symbol for terrain into topology type; used for remembered terrain when mimics pose as furniture */ int @@ -1089,5 +1094,6 @@ invalid_shop_shape(struct mkroom *sroom) } return FALSE; } +#endif /* !SFCTOOL */ /*mkroom.c*/ diff --git a/src/nhlua.c b/src/nhlua.c index 0a77eb108..3ed150392 100644 --- a/src/nhlua.c +++ b/src/nhlua.c @@ -25,6 +25,7 @@ struct e; +#ifndef SFCTOOL /* lua_CFunction prototypes */ #ifdef DUMPLOG staticfn int nhl_dump_fmtstr(lua_State *); @@ -91,7 +92,9 @@ staticfn void nhl_warn(void *, const char *, int); staticfn void nhl_clearfromtable(lua_State *, int, int, struct e *); staticfn int nhl_panic(lua_State *); staticfn void nhl_hookfn(lua_State *, lua_Debug *); +#endif /* !SFCTOOL */ +#ifndef SFCTOOL static const char *const nhcore_call_names[NUM_NHCORE_CALLS] = { "start_new_game", "restore_old_game", @@ -102,6 +105,7 @@ static const char *const nhcore_call_names[NUM_NHCORE_CALLS] = { "leave_tutorial", }; static boolean nhcore_call_available[NUM_NHCORE_CALLS]; +#endif /* internal structure that hangs off L->ud (but use lua_getallocf() ) * Note that we use it for both memory use tracking and instruction counting. @@ -126,6 +130,7 @@ typedef struct nhl_user_data { #endif } nhl_user_data; +#ifndef SFCTOOL static lua_State *luapat; /* instance for file pattern matching */ void @@ -1264,20 +1269,26 @@ get_nh_lua_variables(void) RESTORE_WARNING_UNREACHABLE_CODE -/* char *lua_data; */ +#endif /* !SFCTOOL */ + +#ifdef SFCTOOL +char *lua_data; +#endif /* save nh_lua_variables table to file */ void save_luadata(NHFILE *nhfp) { unsigned lua_data_len; +#ifndef SFCTOOL char *lua_data = get_nh_lua_variables(); /* note: '\0' terminated */ +#endif if (!lua_data) lua_data = dupstr(emptystr); lua_data_len = Strlen(lua_data) + 1; /* +1: include the terminator */ Sfo_unsigned(nhfp, &lua_data_len, "luadata-lua_data_len"); - Sfo_char(nhfp, lua_data, "lua_data", lua_data_len); + Sfo_char(nhfp, lua_data, "luadata", lua_data_len); free(lua_data); } @@ -1286,18 +1297,25 @@ void restore_luadata(NHFILE *nhfp) { unsigned lua_data_len = 0; +#ifndef SFCTOOL char *lua_data; +#endif /* !SFCTOOL */ Sfi_unsigned(nhfp, &lua_data_len, "luadata-lua_data_len"); lua_data = (char *) alloc(lua_data_len); Sfi_char(nhfp, lua_data, "luadata", lua_data_len); + +#ifndef SFCTOOL if (!gl.luacore) l_nhcore_init(); luaL_loadstring(gl.luacore, lua_data); free(lua_data); nhl_pcall_handle(gl.luacore, 0, 0, "restore_luadata", NHLpa_panic); +#endif /* !SFCTOOL */ } +#ifndef SFCTOOL + /* local stairs = stairways(); */ staticfn int nhl_stairways(lua_State *L) @@ -2977,6 +2995,8 @@ nhlL_newstate(nhl_sandbox_info *sbi, const char *name) return L; } +#endif /* !SFCTOOL */ + /* (See end of comment for conclusion.) to make packages safe, we need something like: diff --git a/src/o_init.c b/src/o_init.c index 04730e3a2..c62ca0a0c 100644 --- a/src/o_init.c +++ b/src/o_init.c @@ -5,6 +5,7 @@ #include "hack.h" +#ifndef SFCTOOL staticfn void setgemprobs(d_level *); staticfn void randomize_gem_colors(void); staticfn void shuffle(int, int, boolean); @@ -403,6 +404,7 @@ savenames(NHFILE *nhfp) } } } +#endif /* !SFCTOOL */ void restnames(NHFILE *nhfp) @@ -426,11 +428,14 @@ restnames(NHFILE *nhfp) Sfi_char(nhfp, objects[i].oc_uname, "names-oc_uname", (int) len); } } +#ifndef SFCTOOL #ifdef TILES_IN_GLYPHMAP shuffle_tiles(); #endif +#endif } +#ifndef SFCTOOL void discover_object( int oindx, @@ -562,6 +567,7 @@ sortloot_descr(int otyp, char *outbuf) sl_cookie.orderclass, sl_cookie.subclass, sl_cookie.disco); return outbuf; } +#endif /* !SFCTOOL */ #define DISCO_BYCLASS 0 /* by discovery order within each class */ #define DISCO_SORTLOOT 1 /* by discovery order within each subclass */ @@ -577,6 +583,8 @@ static const char *const disco_orders_descr[] = { (char *) 0 }; +#ifndef SFCTOOL + int choose_disco_sort( int mode) /* 0 => 'O' cmd, 1 => full discoveries; 2 => class disco */ @@ -1110,6 +1118,7 @@ rename_disco(void) destroy_nhwindow(tmpwin); return; } +#endif /* !SFCTOOL */ void get_sortdisco(char *opts, boolean cnf) diff --git a/src/region.c b/src/region.c index b0aeb1127..796d48fc1 100644 --- a/src/region.c +++ b/src/region.c @@ -13,6 +13,7 @@ #define NO_CALLBACK (-1) void free_region(NhRegion *); +#ifndef SFCTOOL boolean inside_gas_cloud(genericptr, genericptr); boolean expire_gas_cloud(genericptr, genericptr); boolean inside_rect(NhRect *, int, int); @@ -253,6 +254,7 @@ clone_region(NhRegion *reg) } #endif /*0*/ +#endif /* !SFCTOOL */ /* * Free mem from region. @@ -273,6 +275,7 @@ free_region(NhRegion *reg) } } +#ifndef SFCTOOL /* * Add a region to the list. * This actually activates the region. @@ -381,6 +384,7 @@ remove_region(NhRegion *reg) } free_region(reg); } +#endif /* !SFCTOOL */ /* * Remove all regions and clear all related data. This must be done @@ -400,6 +404,7 @@ clear_regions(void) gr.regions = (NhRegion **) 0; } +#ifndef SFCTOOL /* * This function is called every turn. * It makes the regions age, if necessary and calls the appropriate @@ -788,6 +793,7 @@ save_regions(NHFILE *nhfp) if (release_data(nhfp)) clear_regions(); } +#endif /* !SFCTOOL */ void rest_regions(NHFILE *nhfp) @@ -872,6 +878,7 @@ rest_regions(NHFILE *nhfp) Sfi_int(nhfp, &r->glyph, "region-glyph"); Sfi_any(nhfp, &r->arg, "region-arg"); } +#ifndef SFCTOOL /* remove expired regions, do not trigger the expire_f callback (yet!); also update monster lists if this data is coming from a bones file */ for (i = svn.n_regions - 1; i >= 0; i--) { @@ -881,8 +888,10 @@ rest_regions(NHFILE *nhfp) else if (ghostly && r->n_monst > 0) reset_region_mids(r); } +#endif /* !SFCTOOL */ } +#ifndef SFCTOOL DISABLE_WARNING_FORMAT_NONLITERAL /* to support '#stats' wizard-mode command */ @@ -1394,5 +1403,6 @@ region_safety(void) if (BlindedTimeout == 1L) make_blinded(0L, TRUE); } +#endif /* !SFCTOOL */ /*region.c*/ diff --git a/src/restore.c b/src/restore.c index 77e4e2383..dc87cb696 100644 --- a/src/restore.c +++ b/src/restore.c @@ -22,6 +22,7 @@ staticfn struct fruit *loadfruitchn(NHFILE *); staticfn void freefruitchn(struct fruit *); staticfn void rest_levl(NHFILE *); staticfn void rest_stairs(NHFILE *); +#ifndef SFCTOOL staticfn void ghostfruit(struct obj *); staticfn boolean restgamestate(NHFILE *); staticfn void restlevelstate(void); @@ -29,10 +30,12 @@ staticfn int restlevelfile(xint8); staticfn void rest_bubbles(NHFILE *); staticfn void restore_gamelog(NHFILE *); staticfn void reset_oattached_mids(boolean); +/* these ones are declared non-static in extern.h if SFCTOOL is defined */ staticfn boolean restgamestate(NHFILE *); staticfn void rest_bubbles(NHFILE *); staticfn void restore_gamelog(NHFILE *); staticfn void restore_msghistory(NHFILE *); +#endif /* * Save a mapping of IDs from ghost levels to the current level. This @@ -47,8 +50,10 @@ struct bucket { } map[N_PER_BUCKET]; }; +#ifndef SFCTOOL staticfn void clear_id_mapping(void); staticfn void add_id_mapping(unsigned, unsigned); +#endif /* SFCTOOL */ #ifdef AMII_GRAPHICS void amii_setpens(int); /* use colors from save file */ @@ -59,6 +64,7 @@ extern int amii_numcolors; #define Is_IceBox(o) ((o)->otyp == ICE_BOX ? TRUE : FALSE) +#ifndef SFCTOOL /* Recalculate svl.level.objects[x][y], since this info was not saved. */ staticfn void @@ -118,6 +124,8 @@ inven_inuse(boolean quietly) } } +#endif /* SFCTOOL */ + staticfn void restlevchn(NHFILE *nhfp) { @@ -147,7 +155,9 @@ restdamage(NHFILE *nhfp) unsigned int dmgcount = 0; int counter; struct damage *tmp_dam; +#ifndef SFCTOOL boolean ghostly = (nhfp->ftype == NHF_BONESFILE); +#endif Sfi_unsigned(nhfp, &dmgcount, "damage-damage_count"); counter = (int) dmgcount; @@ -158,11 +168,13 @@ restdamage(NHFILE *nhfp) tmp_dam = (struct damage *) alloc(sizeof *tmp_dam); Sfi_damage(nhfp, tmp_dam, "damage"); +#ifndef SFCTOOL if (ghostly) tmp_dam->when += (svm.moves - svo.omoves); tmp_dam->next = svl.level.damagelist; svl.level.damagelist = tmp_dam; +#endif /* !SFCTOOL */ } while (--counter > 0); } @@ -199,7 +211,7 @@ restobj(NHFILE *nhfp, struct obj *otmp) } /* omailcmd - feedback mechanism for scroll of mail */ - Sfi_int(nhfp, &buflen, "obj-omail_length"); + Sfi_int(nhfp, &buflen, "obj-omailcmd_length"); if (buflen > 0) { char *omailcmd = (char *) alloc(buflen); @@ -210,7 +222,7 @@ restobj(NHFILE *nhfp, struct obj *otmp) /* omid - monster id number, connecting corpse to ghost */ newomid(otmp); /* superfluous; we're already allocated otmp->oextra */ - Sfi_unsigned(nhfp, &omid, "obj-omid_length"); + Sfi_unsigned(nhfp, &omid, "obj-omid"); OMID(otmp) = omid; } } @@ -221,10 +233,15 @@ restobjchn(NHFILE *nhfp, boolean frozen) struct obj *otmp, *otmp2 = 0; struct obj *first = (struct obj *) 0; int buflen = 0; +#ifndef SFCTOOL boolean ghostly = (nhfp->ftype == NHF_BONESFILE); +#endif + boolean trouble = FALSE; while (1) { Sfi_int(nhfp, &buflen, "obj-obj_length"); + if (!(buflen != -1 || buflen != sizeof (struct obj))) + trouble = TRUE; if (buflen == -1) break; @@ -236,6 +253,7 @@ restobjchn(NHFILE *nhfp, boolean frozen) else otmp2->nobj = otmp; +#ifndef SFCTOOL if (ghostly) { unsigned nid = next_ident(); @@ -250,6 +268,7 @@ restobjchn(NHFILE *nhfp, boolean frozen) */ if (ghostly && !frozen && !age_is_relative(otmp)) otmp->age = svm.moves - svo.omoves + otmp->age; +#endif /* !SFCTOOL */ /* get contents of a container or statue */ if (Has_contents(otmp)) { @@ -261,6 +280,7 @@ restobjchn(NHFILE *nhfp, boolean frozen) otmp3->ocontainer = otmp; } +#ifndef SFCTOOL if (otmp->bypass) otmp->bypass = 0; if (!ghostly) { @@ -272,12 +292,17 @@ restobjchn(NHFILE *nhfp, boolean frozen) if (otmp->o_id == svc.context.spbook.o_id) svc.context.spbook.book = otmp; } +#endif /* !SFADUSTER */ otmp2 = otmp; } if (first && otmp2->nobj) { impossible("Restobjchn: error reading objchn."); otmp2->nobj = 0; } +#ifdef SFCTOOL + nhUse(frozen); +#endif + nhUse(trouble); return first; } @@ -353,8 +378,11 @@ restmonchn(NHFILE *nhfp) { struct monst *mtmp, *mtmp2 = 0; struct monst *first = (struct monst *) 0; - int offset, buflen = 0; + int buflen = 0; +#ifndef SFCTOOL + int offset; boolean ghostly = (nhfp->ftype == NHF_BONESFILE); +#endif while (1) { Sfi_int(nhfp, &buflen, "monst-monst_length"); @@ -369,6 +397,7 @@ restmonchn(NHFILE *nhfp) else mtmp2->nmon = mtmp; +#ifndef SFCTOOL if (ghostly) { unsigned nid = next_ident(); @@ -386,13 +415,21 @@ restmonchn(NHFILE *nhfp) mtmp->mhpmax = DEFUNCT_MONSTER; } } +#endif /* !SFCTOOL */ + if (mtmp->minvent) { struct obj *obj; mtmp->minvent = restobjchn(nhfp, FALSE); +#ifndef SFCTOOL /* restore monster back pointer */ for (obj = mtmp->minvent; obj; obj = obj->nobj) obj->ocarry = mtmp; +#else + nhUse(obj); +#endif } + +#ifndef SFCTOOL if (mtmp->mw) { struct obj *obj; @@ -416,12 +453,15 @@ restmonchn(NHFILE *nhfp) if (mtmp->m_id == svc.context.polearm.m_id) svc.context.polearm.hitmon = mtmp; } +#endif /* !SFCTOOL */ mtmp2 = mtmp; } +#ifndef SFCTOOL if (first && mtmp2->nmon) { impossible("Restmonchn: error reading monchn."); mtmp2->nmon = 0; } +#endif return first; } @@ -456,6 +496,7 @@ freefruitchn(struct fruit *flist) } } +#ifndef SFCTOOL staticfn void ghostfruit(struct obj *otmp) { @@ -470,6 +511,7 @@ ghostfruit(struct obj *otmp) else otmp->spe = fruitadd(oldf->fname, (struct fruit *) 0); } +#endif /* !SFCTOOL */ #ifdef SYSCF #define SYSOPT_CHECK_SAVE_UID sysopt.check_save_uid @@ -477,7 +519,10 @@ ghostfruit(struct obj *otmp) #define SYSOPT_CHECK_SAVE_UID TRUE #endif -staticfn boolean +#ifndef SFCTOOL +staticfn +#endif +boolean restgamestate(NHFILE *nhfp) { int i; @@ -486,15 +531,18 @@ restgamestate(NHFILE *nhfp) struct obj *bc_obj; char timebuf[15]; unsigned long uid = 0; +#ifndef SFCTOOL boolean defer_perm_invent, restoring_special; struct obj *otmp; +#endif Sfi_ulong(nhfp, &uid, "gamestate-uid"); +#ifndef SFCTOOL if (SYSOPT_CHECK_SAVE_UID && uid != (unsigned long) getuid()) { /* strange ... */ if (!gc.converted_savefile_loaded) /* for wizard mode, issue a reminder; for others, treat it - as an attempt to cheat and refuse to restore this file */ + * as an attempt to cheat and refuse to restore this file */ pline("Saved game was not yours."); if (wizard || gc.converted_savefile_loaded) { if (gc.converted_savefile_loaded) @@ -503,7 +551,7 @@ restgamestate(NHFILE *nhfp) return FALSE; } } - +#endif /* SFCTOOL */ newgamecontext = svc.context; /* copy statically init'd context */ Sfi_context_info(nhfp, &svc.context, "gamestate-context"); svc.context.warntype.species = (ismnum(svc.context.warntype.speciesidx)) @@ -519,6 +567,7 @@ restgamestate(NHFILE *nhfp) newgameflags = flags; Sfi_flag(nhfp, &flags, "gamestate-flags"); +#ifndef SFCTOOL /* avoid keeping permanent inventory window up to date during restore (setworn() calls update_inventory); attempting to include the cost of unpaid items before shopkeeper's bill is available is a no-no; @@ -545,16 +594,18 @@ restgamestate(NHFILE *nhfp) #ifdef AMII_GRAPHICS amii_setpens(amii_numcolors); /* use colors from save file */ #endif - +#endif /* !SFCTOOL */ Sfi_you(nhfp, &u, "gamestate-you"); gy.youmonst.cham = u.mcham; +#ifndef SFCTOOL if (restoring_special && iflags.explore_error_flag) { /* savefile has wizard or explore mode, but player is no longer authorized to access either; can't downgrade mode any further, so fail restoration. */ u.uhp = 0; } +#endif Sfi_char(nhfp, timebuf, "gamestate-ubirthday", 14); timebuf[14] = '\0'; @@ -562,6 +613,7 @@ restgamestate(NHFILE *nhfp) Sfi_long(nhfp, &urealtime.realtime, "gamestate-realtime"); Sfi_char(nhfp, timebuf, "gamestate-start_timing", 14); timebuf[14] = '\0'; +#ifndef SFCTOOL urealtime.start_timing = time_from_yyyymmddhhmmss(timebuf); /* current time is the time to use for next urealtime.realtime update */ @@ -590,6 +642,7 @@ restgamestate(NHFILE *nhfp) } /* in case hangup save occurred in midst of level change */ assign_level(&u.uz0, &u.uz); +#endif /* !SFCTOOL */ /* this stuff comes after potential aborted restore attempts */ restore_killers(nhfp); @@ -600,7 +653,7 @@ restgamestate(NHFILE *nhfp) /* restore dangling (not on floor or in inventory) ball and/or chain */ bc_obj = restobjchn(nhfp, FALSE); - +#ifndef SFCTOOL while (bc_obj) { struct obj *nobj = bc_obj->nobj; @@ -609,13 +662,15 @@ restgamestate(NHFILE *nhfp) setworn(bc_obj, bc_obj->owornmask); bc_obj = nobj; } - +#endif gm.migrating_objs = restobjchn(nhfp, FALSE); gm.migrating_mons = restmonchn(nhfp); for (i = 0; i < NUMMONS; ++i) { Sfi_mvitals(nhfp, &svm.mvitals[i], "gamestate-mvitals"); } + +#ifndef SFCTOOL /* * There are some things after this that can have unintended display * side-effects too early in the game. @@ -637,6 +692,7 @@ restgamestate(NHFILE *nhfp) setuwep(otmp); /* (don't need any null check here) */ if (!uwep || uwep->otyp == PICK_AXE || uwep->otyp == GRAPPLING_HOOK) gu.unweapon = TRUE; +#endif /* !SFCTOOL */ restore_dungeon(nhfp); restlevchn(nhfp); @@ -660,15 +716,22 @@ restgamestate(NHFILE *nhfp) restore_msghistory(nhfp); restore_gamelog(nhfp); restore_luadata(nhfp); +#ifndef SFCTOOL /* must come after all mons & objs are restored */ relink_timers(FALSE); relink_light_sources(FALSE); adj_erinys(u.ualign.abuse); /* inventory display is now viable */ iflags.perm_invent = defer_perm_invent; +#else + nhUse(bc_obj); + nhUse(newgamecontext); + nhUse(newgameflags); +#endif /* !SFCTOOL */ return TRUE; } +#ifndef SFCTOOL /* update game state pointers to those valid for the current level (so we don't dereference a wild u.ustuck when saving game state, for instance) */ staticfn void @@ -886,15 +949,20 @@ dorecover(NHFILE *nhfp) check_special_room(FALSE); return 1; } +#endif /* !SFCTOOL */ staticfn void rest_stairs(NHFILE *nhfp) { int buflen = 0; stairway stway = UNDEFINED_VALUES; +#ifndef SFCTOOL stairway *newst; +#endif +#ifndef SFCTOOL stairway_free_all(); +#endif while (1) { Sfi_int(nhfp, &buflen, "stairs-staircount"); if (buflen == -1) @@ -906,11 +974,13 @@ rest_stairs(NHFILE *nhfp) /* stairway dlevel is relative, make it absolute */ stway.tolev.dlevel += u.uz.dlevel; } +#ifndef SFCTOOL stairway_add(stway.sx, stway.sy, stway.up, stway.isladder, &(stway.tolev)); newst = stairway_at(stway.sx, stway.sy); if (newst) newst->u_traversed = stway.u_traversed; +#endif } } @@ -932,7 +1002,8 @@ restcemetery(NHFILE *nhfp, struct cemetery **cemeteryaddr) } else { *cemeteryaddr = 0; } - if ((nhfp->mode & CONVERTING) != 0) { + if (((nhfp->mode & CONVERTING) != 0) + || ((nhfp->mode & UNCONVERTING) != 0)) { struct cemetery *thisbones, *nextbones; /* free the memory */ @@ -958,6 +1029,8 @@ rest_levl(NHFILE *nhfp) } } +#ifndef SFCTOOL + void trickery(char *reason) { @@ -967,14 +1040,17 @@ trickery(char *reason) Strcpy(svk.killer.name, reason ? reason : ""); done(TRICKED); } +#endif /* !SFCTOOL */ void getlev(NHFILE *nhfp, int pid, xint8 lev) { struct trap *trap; +#ifndef SFCTOOL struct monst *mtmp; branch *br; int x, y; +#endif long elapsed = 0L; int hpid = 0; xint8 dlvl = 0; @@ -986,9 +1062,11 @@ getlev(NHFILE *nhfp, int pid, xint8 lev) #endif program_state.in_getlev = TRUE; +#ifndef SFCTOOL if (ghostly) clear_id_mapping(); +#endif /* !SFCTOOL */ #if 0 #if defined(MSDOS) || defined(OS2) @@ -1007,6 +1085,7 @@ getlev(NHFILE *nhfp, int pid, xint8 lev) Sfi_int(nhfp, &hpid, "gamestate-hackpid"); /* CHECK: This may prevent restoration */ Sfi_xint8(nhfp, &dlvl, "gamestate-dlvl"); +#ifndef SFCTOOL if ((pid && pid != hpid) || (lev && dlvl != lev)) { char trickbuf[BUFSZ]; @@ -1019,6 +1098,7 @@ getlev(NHFILE *nhfp, int pid, xint8 lev) pline1(trickbuf); trickery(trickbuf); } +#endif restcemetery(nhfp, &svl.level.bonesinfo); rest_levl(nhfp); @@ -1051,10 +1131,14 @@ getlev(NHFILE *nhfp, int pid, xint8 lev) } rest_rooms(nhfp); /* No joke :-) */ if (svn.nroom) { +#ifndef SFCTOOL gd.doorindex = svr.rooms[svn.nroom - 1].fdoor + svr.rooms[svn.nroom - 1].doorct; } else { gd.doorindex = 0; +#else + gd.doorindex = 0; +#endif /* !SFCTOOL */ } restore_timers(nhfp, RANGE_LEVEL, elapsed); @@ -1080,14 +1164,16 @@ getlev(NHFILE *nhfp, int pid, xint8 lev) dealloc_trap(trap); fobj = restobjchn(nhfp, FALSE); +#ifndef SFCTOOL find_lev_obj(); +#endif /* !SFCTOOL */ /* restobjchn()'s `frozen' argument probably ought to be a callback routine so that we can check for objects being buried under ice */ svl.level.buriedobjlist = restobjchn(nhfp, FALSE); gb.billobjs = restobjchn(nhfp, FALSE); rest_engravings(nhfp); - +#ifndef SFCTOOL /* reset level.monsters for new level */ for (x = 0; x < COLNO; x++) for (y = 0; y < ROWNO; y++) @@ -1133,6 +1219,7 @@ getlev(NHFILE *nhfp, int pid, xint8 lev) if (ghostly || (elapsed > 00 && elapsed > (long) rnd(10))) hide_monst(mtmp); } +#endif /* !SFCTOOL */ restdamage(nhfp); rest_regions(nhfp); @@ -1140,6 +1227,7 @@ getlev(NHFILE *nhfp, int pid, xint8 lev) load_exclusions(nhfp); rest_track(nhfp); +#ifndef SFCTOOL if (ghostly) { stairway *stway = gs.stairs; while (stway) { @@ -1215,6 +1303,11 @@ getlev(NHFILE *nhfp, int pid, xint8 lev) if (ghostly) clear_id_mapping(); program_state.in_getlev = FALSE; +#else + nhUse(pid); + nhUse(lev); +#endif /* !SFCTOOL */ + program_state.in_getlev = FALSE; } /* "name-role-race-gend-algn" occurs very early in a save file; sometimes we @@ -1247,7 +1340,10 @@ get_plname_from_file( } /* restore Plane of Water's air bubbles and Plane of Air's clouds */ -staticfn void +#ifndef SFCTOOL +staticfn +#endif +void rest_bubbles(NHFILE *nhfp) { xint8 bbubbly; @@ -1265,7 +1361,10 @@ rest_bubbles(NHFILE *nhfp) restore_waterlevel(nhfp); } -staticfn void +#ifndef SFCTOOL +staticfn +#endif +void restore_gamelog(NHFILE *nhfp) { int slen = 0; @@ -1281,11 +1380,16 @@ restore_gamelog(NHFILE *nhfp) Sfi_char(nhfp, msg, "gamelog-gamelog_text", slen); msg[slen] = '\0'; Sfi_gamelog_line(nhfp, &tmp, "gamelog-gamelog_line"); +#ifndef SFCTOOL gamelog_add(tmp.flags, tmp.turn, msg); +#endif /* !SFCTOOL */ } } -staticfn void +#ifndef SFCTOOL +staticfn +#endif +void restore_msghistory(NHFILE *nhfp) { int msgsize = 0; @@ -1300,14 +1404,20 @@ restore_msghistory(NHFILE *nhfp) panic("restore_msghistory: msg too big (%d)", msgsize); Sfi_char(nhfp, msg, "msghistory-msg", msgsize); msg[msgsize] = '\0'; +#ifndef SFCTOOL putmsghistory(msg, TRUE); +#endif /* !SFCTOOL */ ++msgcount; } +#ifndef SFCTOOL if (msgcount) putmsghistory((char *) 0, TRUE); debugpline1("Read %d messages from savefile.", msgcount); +#endif /* !SFCTOOL */ } +#ifndef SFCTOOL + /* Clear all structures for object and monster ID mapping. */ staticfn void clear_id_mapping(void) @@ -1483,5 +1593,6 @@ restore_menu( return (ch > 0) ? 1 : ch; } #endif /* SELECTSAVED */ +#endif /* !SFCTOOL */ /*restore.c*/ diff --git a/src/rumors.c b/src/rumors.c index 2e58d6225..711d08516 100644 --- a/src/rumors.c +++ b/src/rumors.c @@ -41,6 +41,7 @@ * and placed there by 'makedefs'. */ +#ifndef SFCTOOL staticfn void unpadline(char *); staticfn void init_rumors(dlb *); staticfn char *get_rnd_line(dlb *, char *, unsigned, int (*)(int), @@ -615,6 +616,7 @@ save_oracles(NHFILE *nhfp) } } } +#endif /* !SFCTOOL */ void restore_oracles(NHFILE *nhfp) @@ -632,6 +634,7 @@ restore_oracles(NHFILE *nhfp) } } +#ifndef SFCTOOL void outoracle(boolean special, boolean delphi) { @@ -947,5 +950,6 @@ free_CapMons(void) } CapMonSiz = 0; } +#endif /* !SFCTOOL */ /*rumors.c*/ diff --git a/src/save.c b/src/save.c index 4e4f568a3..bc420a041 100644 --- a/src/save.c +++ b/src/save.c @@ -115,7 +115,7 @@ dosave0(void) clear_nhwindow(WIN_MESSAGE); There("seems to be an old save file."); if (y_n("Overwrite the old file?") == 'n') { - //nh_sfconvert(fq_save); + nh_sfconvert(fq_save); nh_compress(fq_save); goto done; } @@ -131,8 +131,7 @@ dosave0(void) goto done; } if (nhfp && nhfp->fplog) { - /* (void) fprintf(nhfp->fplog, "# just opened\n"); */ - nhfp->count = 0L; + nhfp->rcount = nhfp->wcount = 0L; } vision_recalc(2); /* shut down vision to prevent problems @@ -221,7 +220,7 @@ dosave0(void) /* get rid of current level --jgm */ delete_levelfile(ledger_no(&u.uz)); delete_levelfile(0); - ///nh_sfconvert(fq_save); + nh_sfconvert(fq_save); nh_compress(fq_save); /* this should probably come sooner... */ program_state.something_worth_saving = 0; @@ -1144,7 +1143,7 @@ freedynamicdata(void) #endif discard_gamelog(); release_runtime_info(); /* build-time options and version stuff */ - //free_convert_filenames(); + free_convert_filenames(); #endif /* FREE_ALL_MEMORY */ if (VIA_WINDOWPORT()) diff --git a/src/sfbase.c b/src/sfbase.c index 6a62865af..580f5f001 100644 --- a/src/sfbase.c +++ b/src/sfbase.c @@ -4,82 +4,242 @@ #include "hack.h" #include "sfprocs.h" +#ifdef SFCTOOL +//#include "sfproto.h" +#endif /* #define DO_DEBUG */ +//#define TURN_OFF_LOGGING 0x20 +#define TURN_OFF_LOGGING (UNCONVERTING << 1) + struct sf_structlevel_procs sfoprocs[NUM_SAVEFORMATS], sfiprocs[NUM_SAVEFORMATS], zerosfoprocs = {0}, zerosfiprocs = {0}; +struct sf_fieldlevel_procs sfoflprocs[NUM_SAVEFORMATS], sfiflprocs[NUM_SAVEFORMATS], + zerosfoflprocs = {0}, zerosfiflprocs = {0}; -void sf_log(NHFILE *, const char *, size_t, int); +char *sfvalue_aligntyp(aligntyp *a); +char *sfvalue_any(anything *a); +char *sfvalue_genericptr(genericptr a); +char *sfvalue_int16(int16 *a); +char *sfvalue_int32(int32 *a); +char *sfvalue_int64(int64 *a); +char *sfvalue_uchar(uchar *a); +char *sfvalue_uint16(uint16 *a); +char *sfvalue_uint32(uint32 *a); +char *sfvalue_uint64(uint64 *a); +char *sfvalue_size_t(size_t *a); +char *sfvalue_time_t(time_t *a); +char *sfvalue_short(short *a); +char *sfvalue_ushort(ushort *a); +char *sfvalue_int(int *a); +char *sfvalue_unsigned(unsigned *a); +char *sfvalue_long(long *a); +char *sfvalue_ulong(ulong *a); +char *sfvalue_xint8(xint8 *a); +char *sfvalue_xint16(xint16 *a); +char *sfvalue_char(char *a, int n); +char *sfvalue_boolean(boolean *a); +char *sfvalue_schar(schar *a); +char *sfvalue_bitfield(uint8 *a); +char *complex_dump(uchar *a); +char *bitfield_dump(uint8 *a); + +void sf_log(NHFILE *, const char *, size_t, int, char *); + +#if NH_C < 202300L +#define Sfvalue_aligntyp(a) sfvalue_aligntyp(a) +#define Sfvalue_any(a) sfvalue_any(a) +#define Sfvalue_genericptr(a) sfvalue_genericptr(a) +#define Sfvalue_coordxy(a) sfvalue_int16(a) +#define Sfvalue_int16(a) sfvalue_int16(a) +#define Sfvalue_int32(a) sfvalue_int32(a) +#define Sfvalue_int64(a) sfvalue_int64(a) +#define Sfvalue_uchar(a) sfvalue_uchar(a) +#define Sfvalue_uint16(a) sfvalue_uint16(a) +#define Sfvalue_uint32(a) sfvalue_uint32(a) +#define Sfvalue_uint64(a) sfvalue_uint64(a) +#define Sfvalue_size_t(a) sfvalue_size_t(a) +#define Sfvalue_time_t(a) sfvalue_time_t(a) +#define Sfvalue_short(a) sfvalue_short(a) +#define Sfvalue_ushort(a) sfvalue_ushort(a) +#define Sfvalue_int(a) sfvalue_int(a) +#define Sfvalue_unsigned(a) sfvalue_unsigned(a) +#define Sfvalue_long(a) sfvalue_long(a) +#define Sfvalue_ulong(a) sfvalue_ulong(a) +#define Sfvalue_xint8(a) sfvalue_xint8(a) +#define Sfvalue_xint16(a) sfvalue_xint16(a) + +#else + +#define sfvalue(x) \ + _Generic( (x), \ + anything *: sfvalue_any, \ + genericptr_t *: sfvalue_genericptr, \ + int16_t *: sfvalue_int16, \ + int32_t *: sfvalue_int32, \ + int64_t *: sfvalue_int64, \ + uchar *: sfvalue_uchar, \ + uint16_t *: sfvalue_uint16, \ + uint32_t *: sfvalue_uint32, \ + uint64_t *: sfvalue_uint64, \ + long *: sfvalue_long, \ + unsigned long *: sfvalue_ulong, \ + xint8 *: sfvalue_xint8 \ + )(x) + +#define Sfvalue_any(a) sfvalue(a) +#define Sfvalue_aligntyp(a) sfvalue(a) +#define Sfvalue_genericptr(a) sfvalue(a) +#define Sfvalue_coordxy(a) sfvalue(a) +#define Sfvalue_int16(a) sfvalue(a) +#define Sfvalue_int32(a) sfvalue(a) +#define Sfvalue_int64(a) sfvalue(a) +#define Sfvalue_uchar(a) sfvalue(a) +#define Sfvalue_unsigned(a) sfvalue(a) +#define Sfvalue_uchar(a) sfvalue(a) +#define Sfvalue_uint16(a) sfvalue(a) +#define Sfvalue_uint32(a) sfvalue(a) +#define Sfvalue_uint64(a) sfvalue(a) +#define Sfvalue_size_t(a) sfvalue(a) +#define Sfvalue_time_t(a) sfvalue(a) +#define Sfvalue_short(a) sfvalue(a) +#define Sfvalue_ushort(a) sfvalue(a) +#define Sfvalue_int(a) sfvalue(a) +#define Sfvalue_unsigned(a) sfvalue(a) +#define Sfvalue_long(a) sfvalue(a) +#define Sfvalue_ulong(a) sfvalue(a) +#define Sfvalue_xint8(a) sfvalue(a) +#define Sfvalue_xint16(a) sfvalue(a) +#endif + +/* not in _Generic */ +#define Sfvalue_char(a, d) sfvalue_char(a, d) +#define Sfvalue_boolean(a) sfvalue_boolean(a) +#define Sfvalue_schar(a) sfvalue_schar(a) +#define Sfvalue_bitfield(a) sfvalue_bitfield(a) #define SF_A(dtyp) \ -void sfo_##dtyp(NHFILE *nhfp, dtyp *d_##dtyp, const char *myname) \ -{ \ - if (nhfp->fplog) \ - sf_log(nhfp, myname, sizeof *d_##dtyp, 1); \ - if (nhfp->structlevel) { \ - (*sfoprocs[nhfp->fnidx].fn.sf_##dtyp)(nhfp, d_##dtyp, myname); \ - } \ -} \ - \ -void sfi_##dtyp(NHFILE *nhfp, dtyp *d_##dtyp, const char *myname) \ -{ \ - if (nhfp->structlevel) { \ - (*sfiprocs[nhfp->fnidx].fn.sf_##dtyp)(nhfp, d_##dtyp, myname); \ - } \ - if (nhfp->fplog && !nhfp->eof) \ - sf_log(nhfp, myname, sizeof *d_##dtyp, 1); \ - if (nhfp->eof) \ - return; \ - if (((nhfp->mode & CONVERTING) != 0) && nhfp->nhfpconvert) \ - sfo_##dtyp(nhfp->nhfpconvert, d_##dtyp, myname); \ +void sfo_##dtyp(NHFILE *nhfp, dtyp *d_##dtyp, const char *myname) \ +{ \ + if (nhfp->fplog) \ + sf_log(nhfp, myname, sizeof *d_##dtyp, 1, Sfvalue_##dtyp(d_##dtyp)); \ + if (nhfp->structlevel) { \ + (*sfoprocs[nhfp->fnidx].fn.sf_##dtyp)(nhfp, d_##dtyp, myname); \ + } else { \ + FILE *save_fplog = nhfp->fplog; \ + \ + nhfp->fplog = 0; \ + (*sfoflprocs[nhfp->fnidx].fn_x.sf_##dtyp)(nhfp, d_##dtyp, myname); \ + nhfp->fplog = save_fplog; \ + } \ +} \ + \ +void sfi_##dtyp(NHFILE *nhfp, dtyp *d_##dtyp, const char *myname) \ +{ \ + if (nhfp->structlevel) { \ + (*sfiprocs[nhfp->fnidx].fn.sf_##dtyp)(nhfp, d_##dtyp, myname); \ + } else { \ + int save_mode = nhfp->mode; \ + \ + nhfp->mode &= ~(CONVERTING | UNCONVERTING); \ + nhfp->mode |= TURN_OFF_LOGGING; \ + (*sfiflprocs[nhfp->fnidx].fn_x.sf_##dtyp)(nhfp, d_##dtyp, myname); \ + nhfp->mode = save_mode; \ + } \ + if (!nhfp->eof) { \ + if ((((nhfp->mode & CONVERTING) != 0) \ + || ((nhfp->mode & UNCONVERTING) != 0)) && nhfp->nhfpconvert) { \ + sfo_##dtyp(nhfp->nhfpconvert, d_##dtyp, myname); \ + } \ + if (nhfp->fplog) \ + sf_log(nhfp, myname, sizeof *d_##dtyp, 1, \ + Sfvalue_##dtyp(d_##dtyp)); \ + } \ } #define SF_C(keyw, dtyp) \ -void sfo_##dtyp(NHFILE *nhfp, keyw dtyp *d_##dtyp, const char *myname) \ -{ \ - \ - if (nhfp->structlevel) { \ - (*sfoprocs[nhfp->fnidx].fn.sf_##dtyp)(nhfp, d_##dtyp, myname); \ - } \ - if (nhfp->fplog && !nhfp->eof) \ - sf_log(nhfp, myname, sizeof *d_##dtyp, 1); \ -} \ - \ -void sfi_##dtyp(NHFILE *nhfp, keyw dtyp *d_##dtyp, const char *myname) \ -{ \ - if (nhfp->structlevel) { \ - (*sfiprocs[nhfp->fnidx].fn.sf_##dtyp)(nhfp, d_##dtyp, myname); \ - } \ - if (nhfp->fplog && !nhfp->eof) \ - sf_log(nhfp, myname, sizeof *d_##dtyp, 1); \ - if (nhfp->eof) \ - return; \ - if (((nhfp->mode & CONVERTING) != 0) && nhfp->nhfpconvert) \ - sfo_##dtyp(nhfp->nhfpconvert, d_##dtyp, myname); \ +void sfo_##dtyp(NHFILE *nhfp, keyw dtyp *d_##dtyp, const char *myname) \ +{ \ + if (nhfp->fplog) \ + sf_log(nhfp, myname, sizeof *d_##dtyp, 1, \ + complex_dump((uchar *) d_##dtyp)); \ + if (nhfp->structlevel) { \ + (*sfoprocs[nhfp->fnidx].fn.sf_##dtyp)(nhfp, d_##dtyp, myname); \ + } else { \ + FILE *save_fplog = nhfp->fplog; \ + \ + nhfp->fplog = 0; \ + (*sfoflprocs[nhfp->fnidx].fn_x.sf_##dtyp)(nhfp, d_##dtyp, myname); \ + nhfp->fplog = save_fplog; \ + } \ +} \ + \ +void sfi_##dtyp(NHFILE *nhfp, keyw dtyp *d_##dtyp, const char *myname) \ +{ \ + if (nhfp->structlevel) { \ + (*sfiprocs[nhfp->fnidx].fn.sf_##dtyp)(nhfp, d_##dtyp, myname); \ + } else { \ + int save_mode = nhfp->mode; \ + \ + nhfp->mode &= ~(CONVERTING | UNCONVERTING); \ + nhfp->mode |= TURN_OFF_LOGGING; \ + (*sfiflprocs[nhfp->fnidx].fn_x.sf_##dtyp)(nhfp, d_##dtyp, myname); \ + nhfp->mode = save_mode; \ + } \ + if (!nhfp->eof) { \ + if ((((nhfp->mode & CONVERTING) != 0) \ + || ((nhfp->mode & UNCONVERTING) != 0)) \ + && nhfp->nhfpconvert) { \ + sfo_##dtyp(nhfp->nhfpconvert, d_##dtyp, myname); \ + } \ + if (nhfp->fplog) \ + sf_log(nhfp, myname, sizeof *d_##dtyp, 1, \ + complex_dump((uchar *) d_##dtyp)); \ + } \ } - + #define SF_X(xxx, dtyp) \ -void sfo_##dtyp(NHFILE *nhfp, xxx *d_##dtyp, const char *myname, int bfsz) \ -{ \ - if (nhfp->structlevel) { \ - (*sfoprocs[nhfp->fnidx].fn.sf_##dtyp)(nhfp, d_##dtyp, myname, bfsz); \ - } \ - if (nhfp->fplog && !nhfp->eof) \ - sf_log(nhfp, myname, sizeof *d_##dtyp, 1); \ -} \ - \ -void sfi_##dtyp(NHFILE *nhfp, xxx *d_##dtyp, const char *myname, int bfsz) \ -{ \ - if (nhfp->structlevel) { \ - (*sfiprocs[nhfp->fnidx].fn.sf_##dtyp)(nhfp, d_##dtyp, myname, bfsz); \ - } \ - if (nhfp->fplog && !nhfp->eof) \ - sf_log(nhfp, myname, sizeof *d_##dtyp, 1); \ - if (nhfp->eof) \ - return; \ - if (((nhfp->mode & CONVERTING) != 0) && nhfp->nhfpconvert) \ - sfo_##dtyp(nhfp->nhfpconvert, d_##dtyp, myname, bfsz); \ +void sfo_##dtyp(NHFILE *nhfp, xxx *d_##dtyp, const char *myname, int bfsz) \ +{ \ + if (nhfp->fplog) \ + sf_log(nhfp, myname, sizeof *d_##dtyp, 1, \ + Sfvalue_##dtyp(d_##dtyp)); \ + if (nhfp->structlevel) { \ + (*sfoprocs[nhfp->fnidx].fn.sf_##dtyp)(nhfp, d_##dtyp, myname, bfsz); \ + } else { \ + FILE *save_fplog = nhfp->fplog; \ + \ + nhfp->fplog = 0; \ + (*sfoflprocs[nhfp->fnidx].fn_x.sf_##dtyp)(nhfp, d_##dtyp, myname, bfsz); \ + nhfp->fplog = save_fplog; \ + } \ + if (nhfp->fplog && !nhfp->eof) \ + sf_log(nhfp, myname, sizeof *d_##dtyp, 1, Sfvalue_##dtyp(d_##dtyp)); \ +} \ + \ +void sfi_##dtyp(NHFILE *nhfp, xxx *d_##dtyp, const char *myname, int bfsz) \ +{ \ + if (nhfp->structlevel) { \ + (*sfiprocs[nhfp->fnidx].fn.sf_##dtyp)(nhfp, d_##dtyp, myname, bfsz); \ + } else { \ + int save_mode = nhfp->mode; \ + \ + nhfp->mode &= ~(CONVERTING | UNCONVERTING); \ + nhfp->mode |= TURN_OFF_LOGGING; \ + (*sfiflprocs[nhfp->fnidx].fn_x.sf_##dtyp)(nhfp, d_##dtyp, myname, bfsz); \ + nhfp->mode = save_mode; \ + } \ + if (!nhfp->eof) { \ + if ((((nhfp->mode & CONVERTING) != 0) \ + || ((nhfp->mode & UNCONVERTING) != 0)) \ + && nhfp->nhfpconvert) { \ + sfo_##dtyp(nhfp->nhfpconvert, d_##dtyp, myname, bfsz); \ + } \ + if (nhfp->fplog) \ + sf_log(nhfp, myname, sizeof *d_##dtyp, 1, \ + dtyp##_dump(d_##dtyp)); \ + } \ } SF_C(struct, arti_info) @@ -123,14 +283,13 @@ SF_C(struct, spell) SF_C(struct, stairway) SF_C(struct, s_level) SF_C(struct, trap) -SF_C(struct, version_info) SF_C(struct, you) SF_C(union, any) SF_A(aligntyp) SF_A(boolean) SF_A(coordxy) -SF_A(genericptr) +//SF_A(genericptr) SF_A(int) SF_A(int16) SF_A(int32) @@ -149,15 +308,22 @@ SF_A(unsigned) SF_A(ushort) SF_A(xint16) SF_A(xint8) +SF_X(uint8_t, bitfield) void sfo_char(NHFILE *nhfp, char *d_char, const char *myname, int cnt) { + if (nhfp->fplog) + sf_log(nhfp, myname, sizeof(char), cnt, Sfvalue_char(d_char, cnt)); if (nhfp->structlevel) { (*sfoprocs[nhfp->fnidx].fn.sf_char)(nhfp, d_char, myname, cnt); + } else { + FILE *save_fplog = nhfp->fplog; + + nhfp->fplog = 0; + (*sfoflprocs[nhfp->fnidx].fn_x.sf_char)(nhfp, d_char, myname, cnt); + nhfp->fplog = save_fplog; } - if (nhfp->fplog && !nhfp->eof) - sf_log(nhfp, myname, sizeof (char), cnt); } void @@ -165,31 +331,379 @@ sfi_char(NHFILE *nhfp, char *d_char, const char *myname, int cnt) { if (nhfp->structlevel) { (*sfiprocs[nhfp->fnidx].fn.sf_char)(nhfp, d_char, myname, cnt); + } else { + int save_mode = nhfp->mode; + + nhfp->mode &= ~(CONVERTING | UNCONVERTING); + nhfp->mode |= TURN_OFF_LOGGING; + (*sfiflprocs[nhfp->fnidx].fn_x.sf_char)(nhfp, d_char, myname, cnt); + nhfp->mode = save_mode; + } + if (!nhfp->eof) { + if ((((nhfp->mode & CONVERTING) != 0) + || ((nhfp->mode & UNCONVERTING) != 0)) + && nhfp->nhfpconvert) { + sfo_char(nhfp->nhfpconvert, d_char, myname, cnt); + } + if (nhfp->fplog) + sf_log(nhfp, myname, sizeof(char), cnt, + Sfvalue_char(d_char, cnt)); + } +} + +void +sfo_genericptr(NHFILE *nhfp, void **d_genericptr, const char *myname) +{ + if (nhfp->fplog) + sf_log(nhfp, myname, sizeof *d_genericptr, 1, + Sfvalue_genericptr(d_genericptr)); + if (nhfp->structlevel) { + (*sfoprocs[nhfp->fnidx].fn.sf_genericptr)(nhfp, d_genericptr, myname); + } else { + FILE *save_fplog = nhfp->fplog; + nhfp->fplog = 0; + (*sfoflprocs[nhfp->fnidx].fn_x.sf_genericptr)(nhfp, d_genericptr, + myname); + nhfp->fplog = save_fplog; + } +} +void +sfi_genericptr(NHFILE *nhfp, void **d_genericptr, const char *myname) +{ + if (nhfp->structlevel) { + (*sfiprocs[nhfp->fnidx].fn.sf_genericptr)(nhfp, d_genericptr, myname); + } else { + int save_mode = nhfp->mode; + nhfp->mode &= ~(CONVERTING | UNCONVERTING); + nhfp->mode |= TURN_OFF_LOGGING; + (*sfiflprocs[nhfp->fnidx].fn_x.sf_genericptr)(nhfp, d_genericptr, + myname); + nhfp->mode = save_mode; + } + if (!nhfp->eof) { + if ((((nhfp->mode & CONVERTING) != 0) || ((nhfp->mode & UNCONVERTING) != 0)) + && nhfp->nhfpconvert) { + sfo_genericptr(nhfp->nhfpconvert, d_genericptr, myname); + } + if (nhfp->fplog) + sf_log(nhfp, myname, sizeof *d_genericptr, 1, + Sfvalue_genericptr(d_genericptr)); + } +} + +void +sfo_version_info(NHFILE *nhfp, struct version_info *d_version_info, + const char *myname) +{ + if (nhfp->fplog) + sf_log(nhfp, myname, sizeof *d_version_info, 1, + complex_dump((uchar *) d_version_info)); + if (nhfp->structlevel) { + (*sfoprocs[nhfp->fnidx].fn.sf_version_info)(nhfp, d_version_info, + myname); + } else { + FILE *save_fplog = nhfp->fplog; + nhfp->fplog = 0; + (*sfoflprocs[nhfp->fnidx].fn_x.sf_version_info)(nhfp, d_version_info, + myname); + nhfp->fplog = save_fplog; + } +} +void +sfi_version_info(NHFILE *nhfp, struct version_info *d_version_info, + const char *myname) +{ + if (nhfp->structlevel) { + (*sfiprocs[nhfp->fnidx].fn.sf_version_info)(nhfp, d_version_info, + myname); + } else { + int save_mode = nhfp->mode; + nhfp->mode &= ~(CONVERTING | UNCONVERTING); + nhfp->mode |= TURN_OFF_LOGGING; + (*sfiflprocs[nhfp->fnidx].fn_x.sf_version_info)(nhfp, d_version_info, + myname); + nhfp->mode = save_mode; + } + if (!nhfp->eof) { + if ((((nhfp->mode & CONVERTING) != 0) || ((nhfp->mode & UNCONVERTING) != 0)) + && nhfp->nhfpconvert) { + d_version_info->feature_set |= SFCTOOL_BIT; + sfo_version_info(nhfp->nhfpconvert, d_version_info, myname); + } + if (nhfp->fplog) + sf_log(nhfp, myname, sizeof *d_version_info, 1, + complex_dump((uchar *) d_version_info)); } - if (nhfp->fplog && !nhfp->eof) - sf_log(nhfp, myname, sizeof (char), cnt); - if (nhfp->eof) - return; - if (((nhfp->mode & CONVERTING) != 0) && nhfp->nhfpconvert) - sfo_char(nhfp->nhfpconvert, d_char, myname, cnt); } -SF_X(uint8_t, bitfield) /* ---------------------------------------------------------------*/ void -sf_log(NHFILE *nhfp, const char *t1, size_t sz, int cnt) +sf_log(NHFILE *nhfp, const char *t1, size_t sz, int cnt, char *txtvalue) { FILE *fp = nhfp->fplog; + long *iocount; + boolean dolog = ((nhfp->mode & TURN_OFF_LOGGING) == 0); - if (fp) { - (void) fprintf(fp, "%ld %s sz=%zu cnt=%d\n", - nhfp->count++, - t1, sz, cnt); + if (fp && dolog) { + iocount = ((nhfp->mode & WRITING) == 0) ? &nhfp->rcount : &nhfp->wcount; + (void) fprintf(fp, "%08ld %s sz=%zu cnt=%d |%s|\n", + *iocount, + t1, sz, cnt, txtvalue); +// (*iocount)++; +// if (*iocount == 87) +// __debugbreak(); fflush(fp); } } +char *sfvalue_char(char *a, int n) +{ + int i; + static char buf[120]; + char *cp; + + cp = &buf[0]; + if (n < (int) (sizeof buf - 1)) + buf[n] = '\0'; + else + buf[(int) (sizeof buf - 1)] = '\0'; + for (i = 0; i < n; ++i, ++cp, ++a) + *cp = *a; + *cp = '\0'; + return buf; +} + +char *sfvalue_boolean(boolean *a) +{ + static char buf[20]; + + Snprintf(buf, sizeof buf, "%s", + (*a == 0) ? "false" : "true"); + return buf; +} + +char *sfvalue_schar(schar *a) +{ + static char buf[20]; + + Snprintf(buf, sizeof buf, "%d", (int) *a); + return buf; +} + +char * sfvalue_aligntyp(aligntyp *a) +{ + static char buf[20]; + + Snprintf(buf, sizeof buf, "%d", (int) *a); + return buf; +} + +char * +sfvalue_any(anything *a) +{ + static char buf[20]; +#ifdef UNIX + Snprintf(buf, sizeof buf, + "%ld", + a->a_int64); +#else + Snprintf(buf, sizeof buf, + "%lld", + a->a_int64); +#endif + return buf; +} + +char * +sfvalue_genericptr(genericptr a) +{ + static char buf[20]; + + Snprintf(buf, sizeof buf, "%s", + (a == 0) ? "0" : "glorkum"); + return buf; +} + +char * sfvalue_int16(int16 *a) +{ + static char buf[20]; + + Snprintf(buf, sizeof buf, "%d", *a); + return buf; +} + +char * sfvalue_int32(int32 *a) +{ + static char buf[20]; + + Snprintf(buf, sizeof buf, "%d", *a); + return buf; +} + +char * sfvalue_int64(int64 *a) +{ + static char buf[20]; +#ifdef UNIX + Snprintf(buf, sizeof buf, "%ld", *a); +#else + Snprintf(buf, sizeof buf, "%lld", *a); +#endif + return buf; +} + +char * sfvalue_uchar(uchar *a) +{ + static char buf[20]; + unsigned x; + + x = *a; + Snprintf(buf, sizeof buf, "%03u", x); + return buf; +} + +char * sfvalue_uint16(uint16 *a) +{ + static char buf[20]; + + Snprintf(buf, sizeof buf, "%u", (uint) *a); + return buf; +} + +char * sfvalue_uint32(uint32 *a) +{ + static char buf[20]; + + Snprintf(buf, sizeof buf, "%u", *a); + return buf; +} + +char * sfvalue_uint64(uint64 *a) +{ + static char buf[20]; + +#ifdef UNIX + Snprintf(buf, sizeof buf, "%lu", *a); +#else + Snprintf(buf, sizeof buf, "%llu", *a); +#endif + return buf; +} + +char * sfvalue_size_t(size_t *a UNUSED) +{ + static char buf[20]; + + Snprintf(buf, sizeof buf, "%s", (char *) ""); + return buf; +} + +char * sfvalue_time_t(time_t *a UNUSED) +{ + static char buf[20]; + + Snprintf(buf, sizeof buf, "%s", (char *) ""); + return buf; +} + +char * sfvalue_short(short *a) +{ + static char buf[20]; + + Snprintf(buf, sizeof buf, "%d", (int) *a); + return buf; +} + +char * sfvalue_ushort(ushort *a) +{ + static char buf[20]; + + Snprintf(buf, sizeof buf, "%u", (unsigned) *a); + return buf; +} + +char * sfvalue_int(int *a) +{ + static char buf[20]; + + Snprintf(buf, sizeof buf, "%d", *a); + return buf; +} + +char * sfvalue_unsigned(unsigned *a) +{ + static char buf[20]; + + Snprintf(buf, sizeof buf, "%u", *a); + return buf; +} + +char * sfvalue_long(long *a) +{ + static char buf[20]; + + Snprintf(buf, sizeof buf, "%ld", *a); + return buf; +} + +char * sfvalue_ulong(ulong *a) +{ + static char buf[20]; + + Snprintf(buf, sizeof buf, "%lu", *a); + return buf; +} + +char * sfvalue_xint8(xint8 *a) +{ + static char buf[20]; + + Snprintf(buf, sizeof buf, "%d", (int) *a); + return buf; +} + +char * sfvalue_xint16(xint16 *a) +{ + static char buf[20]; + + + Snprintf(buf, sizeof buf, "%d", (int) *a); + return buf; +} + +char * +sfvalue_bitfield(uint8 *a) +{ + static char buf[20]; + + Snprintf(buf, sizeof buf, "%u", (uint) *a); + return buf; +} + +char * +bitfield_dump(uint8 *a) +{ + static char buf[20]; + + Snprintf(buf, sizeof buf, "%u", (uint) *a); + return buf; +} +char * +complex_dump(uchar *a) +{ + int i; + uchar *uc = a; + static char buf[50]; + unsigned x[10]; + + for (i = 0; i < SIZE(x); ++i) { + x[i] = *uc++; + } + Snprintf(buf, sizeof buf, "%03x %03x %03x %03x %03x %03x %03x %03x %03x %03x", + x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7], x[8], x[9]); + buf[40] = '\0'; + return buf; +} /* *---------------------------------------------------------------------------- * initialize the function pointers. These are called from initoptions_init(). @@ -203,7 +717,461 @@ sf_init(void) sfiprocs[invalid] = zerosfiprocs; sfoprocs[historical] = historical_sfo_procs; sfiprocs[historical] = historical_sfi_procs; + sfoflprocs[exportascii] = zerosfoflprocs; + sfiflprocs[exportascii] = zerosfiflprocs; } +void +sf_setprocs(int idx, struct sf_structlevel_procs *sfi, struct sf_structlevel_procs *sfo) +{ + sfoprocs[idx] = *sfo; + sfiprocs[idx] = *sfi; +} +void +sf_setflprocs(int idx, struct sf_fieldlevel_procs *flsfi, + struct sf_fieldlevel_procs *flsfo) +{ + sfoflprocs[idx] = *flsfo; + sfiflprocs[idx] = *flsfi; +} +#ifndef SFCTOOL +void normalize_pointers_any(union any *d_any); +void normalize_pointers_align(struct align *d_align); +void normalize_pointers_arti_info(struct arti_info *d_arti_info); +void normalize_pointers_attribs(struct attribs *d_attribs); +void normalize_pointers_bill_x(struct bill_x *d_bill_x); +void normalize_pointers_branch(struct branch *d_branch); +void normalize_pointers_bubble(struct bubble *d_bubble); +void normalize_pointers_cemetery(struct cemetery *d_cemetery); +void normalize_pointers_context_info(struct context_info *d_context_info); +void normalize_pointers_achievement_tracking( + struct achievement_tracking *d_achievement_tracking); +void normalize_pointers_book_info(struct book_info *d_book_info); +void normalize_pointers_dig_info(struct dig_info *d_dig_info); +void normalize_pointers_engrave_info(struct engrave_info *d_engrave_info); +void normalize_pointers_obj_split(struct obj_split *d_obj_split); +void normalize_pointers_polearm_info(struct polearm_info *d_polearm_info); +void normalize_pointers_takeoff_info(struct takeoff_info *d_takeoff_info); +void normalize_pointers_tin_info(struct tin_info *d_tin_info); +void normalize_pointers_tribute_info(struct tribute_info *d_tribute_info); +void normalize_pointers_victual_info(struct victual_info *d_victual_info); +void normalize_pointers_warntype_info(struct warntype_info *d_warntype_info); +void normalize_pointers_d_flags(struct d_flags *d_d_flags); +void normalize_pointers_d_level(struct d_level *d_d_level); +void normalize_pointers_damage(struct damage *d_damage); +void normalize_pointers_dest_area(struct dest_area *d_dest_area); +void normalize_pointers_dgn_topology(struct dgn_topology *d_dgn_topology); +void normalize_pointers_dungeon(struct dungeon *d_dungeon); +void normalize_pointers_ebones(struct ebones *d_ebones); +void normalize_pointers_edog(struct edog *d_edog); +void normalize_pointers_egd(struct egd *d_egd); +void normalize_pointers_emin(struct emin *d_emin); +void normalize_pointers_engr(struct engr *d_engr); +void normalize_pointers_epri(struct epri *d_epri); +void normalize_pointers_eshk(struct eshk *d_eshk); +void normalize_pointers_fakecorridor(struct fakecorridor *d_fakecorridor); +void normalize_pointers_fe(struct fe *d_fe); +void normalize_pointers_flag(struct flag *d_flag); +void normalize_pointers_fruit(struct fruit *d_fruit); +void normalize_pointers_gamelog_line(struct gamelog_line *d_gamelog_line); +void normalize_pointers_kinfo(struct kinfo *d_kinfo); +void normalize_pointers_levelflags(struct levelflags *d_levelflags); +void normalize_pointers_linfo(struct linfo *d_linfo); +void normalize_pointers_ls_t(struct ls_t *d_ls_t); +void normalize_pointers_mapseen_feat(struct mapseen_feat *d_mapseen_feat); +void normalize_pointers_mapseen_flags(struct mapseen_flags *d_mapseen_flags); +void normalize_pointers_mapseen_rooms(struct mapseen_rooms *d_mapseen_rooms); +void normalize_pointers_mapseen(struct mapseen *d_mapseen); +void normalize_pointers_mextra(struct mextra *d_mextra); +void normalize_pointers_mkroom(struct mkroom *d_mkroom); +void normalize_pointers_monst(struct monst *d_monst); +void normalize_pointers_mvitals(struct mvitals *d_mvitals); +void normalize_pointers_nhcoord(struct nhcoord *d_nhcoord); +void normalize_pointers_nhrect(struct nhrect *d_nhrect); +void normalize_pointers_novel_tracking(struct novel_tracking *d_novel_tracking); +void normalize_pointers_obj(struct obj *d_obj); +void normalize_pointers_objclass(struct objclass *d_objclass); +void normalize_pointers_oextra(struct oextra *d_oextra); +void normalize_pointers_prop(struct prop *d_prop); +void normalize_pointers_q_score(struct q_score *d_q_score); +void normalize_pointers_rm(struct rm *d_rm); +void normalize_pointers_s_level(struct s_level *d_s_level); +void normalize_pointers_skills(struct skills *d_skills); +void normalize_pointers_spell(struct spell *d_spell); +void normalize_pointers_stairway(struct stairway *d_stairway); +void normalize_pointers_trap(struct trap *d_trap); +void normalize_pointers_u_conduct(struct u_conduct *d_u_conduct); +void normalize_pointers_u_event(struct u_event *d_u_event); +void normalize_pointers_u_have(struct u_have *d_u_have); +void normalize_pointers_u_realtime(struct u_realtime *d_u_realtime); +void normalize_pointers_u_roleplay(struct u_roleplay *d_u_roleplay); +void normalize_pointers_version_info(struct version_info *d_version_info); +void normalize_pointers_vlaunchinfo(union vlaunchinfo *d_vlaunchinfo); +void normalize_pointers_vptrs(union vptrs *d_vptrs); +void normalize_pointers_you(struct you *d_you); +void +normalize_pointers_any(union any *d_any UNUSED) +{ +} +void +normalize_pointers_align(struct align *d_align UNUSED) +{ +} + +void +normalize_pointers_arti_info(struct arti_info *d_arti_info UNUSED) +{ +} + +void +normalize_pointers_attribs(struct attribs *d_attribs UNUSED) +{ +} + +void +normalize_pointers_bill_x(struct bill_x *d_bill_x UNUSED) +{ +} + +void +normalize_pointers_branch(struct branch *d_branch UNUSED) +{ +} + +void +normalize_pointers_bubble(struct bubble *d_bubble UNUSED) +{ +} + +void +normalize_pointers_cemetery(struct cemetery *d_cemetery UNUSED) +{ +} + +void +normalize_pointers_context_info(struct context_info *d_context_info UNUSED) +{ +} + +void +normalize_pointers_achievement_tracking(struct achievement_tracking *d_achievement_tracking UNUSED) +{ +} + +void +normalize_pointers_book_info(struct book_info *d_book_info UNUSED) +{ +} + +void +normalize_pointers_dig_info(struct dig_info *d_dig_info UNUSED) +{ +} + +void +normalize_pointers_engrave_info(struct engrave_info *d_engrave_info UNUSED) +{ +} + +void +normalize_pointers_obj_split(struct obj_split *d_obj_split UNUSED) +{ +} + +void +normalize_pointers_polearm_info(struct polearm_info *d_polearm_info UNUSED) +{ +} + +void +normalize_pointers_takeoff_info(struct takeoff_info *d_takeoff_info UNUSED) +{ +} + +void +normalize_pointers_tin_info(struct tin_info *d_tin_info UNUSED) +{ +} + +void +normalize_pointers_tribute_info(struct tribute_info *d_tribute_info UNUSED) +{ +} + +void +normalize_pointers_victual_info(struct victual_info *d_victual_info UNUSED) +{ +} + +void +normalize_pointers_warntype_info(struct warntype_info *d_warntype_info UNUSED) +{ +} + +void +normalize_pointers_d_flags(struct d_flags *d_d_flags UNUSED) +{ +} + +void +normalize_pointers_d_level(struct d_level *d_d_level UNUSED) +{ +} + +void +normalize_pointers_damage(struct damage *d_damage UNUSED) +{ +} + +void +normalize_pointers_dest_area(struct dest_area *d_dest_area UNUSED) +{ +} + +void +normalize_pointers_dgn_topology(struct dgn_topology *d_dgn_topology UNUSED) +{ +} + +void +normalize_pointers_dungeon(struct dungeon *d_dungeon UNUSED) +{ +} + +void +normalize_pointers_ebones(struct ebones *d_ebones UNUSED) +{ +} + +void +normalize_pointers_edog(struct edog *d_edog UNUSED) +{ +} + +void +normalize_pointers_egd(struct egd *d_egd UNUSED) +{ +} + +void +normalize_pointers_emin(struct emin *d_emin UNUSED) +{ +} + +void +normalize_pointers_engr(struct engr *d_engr UNUSED) +{ +} + +void +normalize_pointers_epri(struct epri *d_epri UNUSED) +{ +} + +void +normalize_pointers_eshk(struct eshk *d_eshk UNUSED) +{ +} + +void +normalize_pointers_fakecorridor(struct fakecorridor *d_fakecorridor UNUSED) +{ +} + +void +normalize_pointers_fe(struct fe *d_fe UNUSED) +{ +} + +void +normalize_pointers_flag(struct flag *d_flag UNUSED) +{ +} + +void +normalize_pointers_fruit(struct fruit *d_fruit UNUSED) +{ +} + +void +normalize_pointers_gamelog_line(struct gamelog_line *d_gamelog_line UNUSED) +{ +} + +void +normalize_pointers_kinfo(struct kinfo *d_kinfo UNUSED) +{ +} + +void +normalize_pointers_levelflags(struct levelflags *d_levelflags UNUSED) +{ +} + +void +normalize_pointers_linfo(struct linfo *d_linfo UNUSED) +{ +} + +void +normalize_pointers_ls_t(struct ls_t *d_ls_t UNUSED) +{ +} + +void +normalize_pointers_mapseen_feat(struct mapseen_feat *d_mapseen_feat UNUSED) +{ +} + +void +normalize_pointers_mapseen_flags(struct mapseen_flags *d_mapseen_flags UNUSED) +{ +} + +void +normalize_pointers_mapseen_rooms(struct mapseen_rooms *d_mapseen_rooms UNUSED) +{ +} + +void +normalize_pointers_mapseen(struct mapseen *d_mapseen UNUSED) +{ +} + +void +normalize_pointers_mextra(struct mextra *d_mextra UNUSED) +{ +} + +void +normalize_pointers_mkroom(struct mkroom *d_mkroom UNUSED) +{ +} + +void +normalize_pointers_monst(struct monst *d_monst UNUSED) +{ +} + +void +normalize_pointers_mvitals(struct mvitals *d_mvitals UNUSED) +{ +} + +void +normalize_pointers_nhcoord(struct nhcoord *d_nhcoord UNUSED) +{ +} + +void +normalize_pointers_nhrect(struct nhrect *d_nhrect UNUSED) +{ +} + +void +normalize_pointers_novel_tracking(struct novel_tracking *d_novel_tracking UNUSED) +{ +} + +void +normalize_pointers_obj(struct obj *d_obj UNUSED) +{ +} + +void +normalize_pointers_objclass(struct objclass *d_objclass UNUSED) +{ +} + +void +normalize_pointers_oextra(struct oextra *d_oextra UNUSED) +{ +} + +void +normalize_pointers_prop(struct prop *d_prop UNUSED) +{ +} + +void +normalize_pointers_q_score(struct q_score *d_q_score UNUSED) +{ +} + +void +normalize_pointers_rm(struct rm *d_rm UNUSED) +{ +} + +void +normalize_pointers_s_level(struct s_level *d_s_level UNUSED) +{ +} + +void +normalize_pointers_skills(struct skills *d_skills UNUSED) +{ +} + +void +normalize_pointers_spell(struct spell *d_spell UNUSED) +{ +} + +void +normalize_pointers_stairway(struct stairway *d_stairway UNUSED) +{ +} + +void +normalize_pointers_trap(struct trap *d_trap UNUSED) +{ +} + +void +normalize_pointers_u_conduct(struct u_conduct *d_u_conduct UNUSED) +{ +} + +void +normalize_pointers_u_event(struct u_event *d_u_event UNUSED) +{ +} + +void +normalize_pointers_u_have(struct u_have *d_u_have UNUSED) +{ +} + +void +normalize_pointers_u_realtime(struct u_realtime *d_u_realtime UNUSED) +{ +} + +void +normalize_pointers_u_roleplay(struct u_roleplay *d_u_roleplay UNUSED) +{ +} + +void +normalize_pointers_version_info(struct version_info *d_version_info UNUSED) +{ +} + +void +normalize_pointers_vlaunchinfo(union vlaunchinfo *d_vlaunchinfo UNUSED) +{ +} + +void +normalize_pointers_vptrs(union vptrs *d_vptrs UNUSED) +{ +} + +void +normalize_pointers_you(struct you *d_you UNUSED) +{ +} +#endif /* SFCTOOL */ diff --git a/src/sfstruct.c b/src/sfstruct.c index c4eda5418..971676c52 100644 --- a/src/sfstruct.c +++ b/src/sfstruct.c @@ -8,6 +8,8 @@ /* #define SFLOGGING */ /* debugging */ +staticfn void sfstruct_read_error(void); + /* historical full struct savings */ #ifdef SAVEFILE_DEBUGGING @@ -29,6 +31,9 @@ staticfn void logging_finish(void); #define SFI_BODY(dt) \ { \ + if (nhfp->eof) { \ + sfstruct_read_error(); \ + } \ mread(nhfp->fd, (genericptr_t) d_##dt, sizeof *d_##dt); \ if (restoreinfo.mread_flags == -1) \ nhfp->eof = TRUE; \ @@ -46,20 +51,37 @@ void historical_sfi_##dtyp(NHFILE *nhfp, dtyp *d_##dtyp, const char *myname UNUSED) \ SFI_BODY(dtyp) +#define SFO_CBODY(dt) \ + { \ + normalize_pointers_##dt(d_##dt); \ + bwrite(nhfp->fd, (genericptr_t) d_##dt, sizeof *d_##dt); \ + } + +#define SFI_CBODY(dt) \ + { \ + if (nhfp->eof) { \ + sfstruct_read_error(); \ + } \ + mread(nhfp->fd, (genericptr_t) d_##dt, sizeof *d_##dt); \ + normalize_pointers_##dt(d_##dt); \ + if (restoreinfo.mread_flags == -1) \ + nhfp->eof = TRUE; \ + } #define SF_C(keyw, dtyp) \ void historical_sfo_##dtyp(NHFILE *, keyw dtyp *d_##dtyp, \ const char *); \ void historical_sfi_##dtyp(NHFILE *, keyw dtyp *d_##dtyp, \ const char *); \ +extern void normalize_pointers_##dtyp(keyw dtyp *d_##dtyp); \ \ void historical_sfo_##dtyp(NHFILE *nhfp, keyw dtyp *d_##dtyp, \ const char *myname UNUSED) \ - SFO_BODY(dtyp) \ + SFO_CBODY(dtyp) \ \ void historical_sfi_##dtyp(NHFILE *nhfp, keyw dtyp *d_##dtyp, \ const char *myname UNUSED) \ - SFI_BODY(dtyp) + SFI_CBODY(dtyp) #define SF_X(xxx, dtyp) \ void historical_sfo_##dtyp(NHFILE *, xxx *d_##dtyp, const char *, int); \ @@ -121,7 +143,7 @@ SF_C(union, any) SF_A(aligntyp) SF_A(boolean) SF_A(coordxy) -SF_A(genericptr_t) +//SF_A(genericptr_t) SF_A(int) SF_A(int16) SF_A(int32) @@ -159,6 +181,32 @@ historical_sfi_char(NHFILE *nhfp, char *d_char, if (restoreinfo.mread_flags == -1) nhfp->eof = TRUE; } +//extern void sfo_genericptr(NHFILE *, void **, const char *); +//extern void sfi_genericptr(NHFILE *, void **, const char *); +//extern void sfo_x_genericptr(NHFILE *, void **, const char *); +//extern void sfi_x_genericptr(NHFILE *, void **, const char *); + +void historical_sfo_genericptr_t(NHFILE *, genericptr_t *d_genericptr_t, + const char *); +void historical_sfi_genericptr_t(NHFILE *, genericptr_t *d_genericptr_t, + const char *); +void +historical_sfo_genericptr_t(NHFILE *nhfp, genericptr_t *d_genericptr_t, + const char *myname UNUSED) +{ + bwrite(nhfp->fd, (genericptr_t) d_genericptr_t, sizeof *d_genericptr_t); +} +void +historical_sfi_genericptr_t(NHFILE *nhfp, genericptr_t *d_genericptr_t, + const char *myname UNUSED) +{ + if (nhfp->eof) { + sfstruct_read_error(); + } + mread(nhfp->fd, (genericptr_t) d_genericptr_t, sizeof *d_genericptr_t); + if (restoreinfo.mread_flags == -1) + nhfp->eof = TRUE; +} SF_X(uint8_t, bitfield) @@ -592,6 +640,7 @@ mread(int fd, genericptr_t buf, unsigned len) restoreinfo.mread_flags = -1; return; } else { +#ifndef SFCTOOL pline("Read %d instead of %u bytes.", (int) rlen, len); display_nhwindow(WIN_MESSAGE, TRUE); /* flush before error() */ if (program_state.restoring) { @@ -600,10 +649,18 @@ mread(int fd, genericptr_t buf, unsigned len) error("Error restoring old game."); } panic("Error reading level file."); +#else + printf("Read %d instead of %u bytes.\n", (int) rlen, len); +#endif } } } +staticfn void +sfstruct_read_error(void) +{ + /* problem */; +} #ifdef SFLOGGING staticfn void @@ -628,4 +685,3 @@ logging_finish(void) icnt = 0L; } #endif - diff --git a/src/timeout.c b/src/timeout.c index dbfa90762..248dde41f 100644 --- a/src/timeout.c +++ b/src/timeout.c @@ -5,6 +5,7 @@ #include "hack.h" +#ifndef SFCTOOL staticfn void stoned_dialogue(void); staticfn void vomiting_dialogue(void); staticfn void sleep_dialogue(void); @@ -2682,6 +2683,7 @@ save_timers(NHFILE *nhfp, int range) } } } +#endif /* !SFCTOOL */ /* * Pull in the structures from disk, but don't recalculate the object and @@ -2705,10 +2707,13 @@ restore_timers(NHFILE *nhfp, int range, long adjust) Sfi_fe(nhfp, curr, "timer"); if (ghostly) curr->timeout += adjust; +#ifndef SFCTOOL insert_timer(curr); +#endif } } +#ifndef SFCTOOL DISABLE_WARNING_FORMAT_NONLITERAL /* to support '#stats' wizard-mode command */ @@ -2753,5 +2758,6 @@ relink_timers(boolean ghostly) } } } +#endif /* !SFCTOOL */ /*timeout.c*/ diff --git a/src/track.c b/src/track.c index 6f455a694..f5b915f22 100644 --- a/src/track.c +++ b/src/track.c @@ -18,6 +18,7 @@ initrack(void) (void) memset((genericptr_t) &utrack, 0, sizeof(utrack)); } +#ifndef SFCTOOL /* add to track */ void settrack(void) @@ -51,6 +52,7 @@ gettrack(coordxy x, coordxy y) } return (coord *) 0; } +#endif /* !SFCTOOL */ /* return TRUE if x,y has hero tracks on it */ boolean diff --git a/src/version.c b/src/version.c index dc1d0e654..04987929c 100644 --- a/src/version.c +++ b/src/version.c @@ -8,6 +8,7 @@ #include "dlb.h" #ifndef MINIMAL_FOR_RECOVER +#ifndef SFCTOOL #ifndef OPTIONS_AT_RUNTIME #define OPTIONS_AT_RUNTIME @@ -357,6 +358,14 @@ comp_times(long filetime) return ((unsigned long) filetime < (unsigned long) nomakedefs.build_time); } #endif +#endif /* !SFCTOOL */ + +#ifdef SFCTOOL +#ifdef wait_synch +#undef wait_synch +#endif +#define wait_synch() +#endif /* SFCTOOL */ boolean check_version( @@ -385,11 +394,13 @@ check_version( version_data->incarnation != nomakedefs.version_number #endif ) { +#ifndef SFCTOOL if (complain) { pline("Version mismatch for file \"%s\".", filename); if (WIN_MESSAGE != WIN_ERR) display_nhwindow(WIN_MESSAGE, TRUE); } +#endif return FALSE; } else if ( (version_data->feature_set & ~nomakedefs.ignored_features) @@ -397,42 +408,18 @@ check_version( || ((utdflags & UTD_SKIP_SANITY1) == 0 && version_data->entity_count != nomakedefs.version_sanity1) ) { +#ifndef SFCTOOL if (complain) { pline("Configuration incompatibility for file \"%s\".", filename); display_nhwindow(WIN_MESSAGE, TRUE); } +#endif return FALSE; } return TRUE; } -void -store_version(NHFILE *nhfp) -{ - struct version_info version_data = { - 0UL, 0UL, 0UL, - }; - - /* actual version number */ - version_data.incarnation = nomakedefs.version_number; - /* bitmask of config settings */ - version_data.feature_set = nomakedefs.version_features; - /* # of monsters and objects */ - version_data.entity_count = nomakedefs.version_sanity1; - - /* bwrite() before bufon() uses plain write() */ - if (nhfp->structlevel) - bufoff(nhfp->fd); - - store_critical_bytes(nhfp); - Sfo_version_info(nhfp, (struct version_info *) &version_data, - "version_info"); - - if (nhfp->structlevel) - bufon(nhfp->fd); - return; -} - +#ifndef SFCTOOL #ifdef AMIGA const char amiga_version_string[] = AMIGA_VERSION_STRING; #endif @@ -518,6 +505,34 @@ dump_version_info(void) release_runtime_info(); return; } +void +store_version(NHFILE *nhfp) +{ + struct version_info version_data = { + 0UL, + 0UL, + 0UL, + }; + /* actual version number */ + version_data.incarnation = nomakedefs.version_number; + /* bitmask of config settings */ + version_data.feature_set = nomakedefs.version_features; + /* # of monsters and objects */ + version_data.entity_count = nomakedefs.version_sanity1; + + /* bwrite() before bufon() uses plain write() */ + if (nhfp->structlevel) + bufoff(nhfp->fd); + + store_critical_bytes(nhfp); + Sfo_version_info(nhfp, (struct version_info *) &version_data, + "version_info"); + + if (nhfp->structlevel) + bufon(nhfp->fd); + return; +} +#endif /* !SFCTOOL */ #endif /* MINIMAL_FOR_RECOVER */ struct critical_sizes_with_names { @@ -662,9 +677,10 @@ store_critical_bytes(NHFILE *nhfp) /* int cmc = 0; */ if (nhfp->mode & WRITING) { - indicate = (nhfp->structlevel) ? 'h' - : (nhfp->fnidx == cnvascii) ? 'a' - : '?'; + indicate = (nhfp->structlevel) ? 'h' + : (nhfp->fnidx == exportascii) + ? 'a' + : '?'; Sfo_char(nhfp, &indicate, "indicate-format", 1); Sfo_char(nhfp, &csc_count, "count-critical_sizes", 1); cnt = (int) csc_count; @@ -693,7 +709,11 @@ store_critical_bytes(NHFILE *nhfp) int uptodate(NHFILE *nhfp, const char *name, unsigned long utdflags) { +#ifdef SFCTOOL + extern struct version_info vers_info; +#else struct version_info vers_info; +#endif char indicator; int sfstatus = 0, idx_1st_mismatch = 0; boolean quietly = (utdflags & UTD_QUIETLY) != 0; @@ -708,19 +728,18 @@ uptodate(NHFILE *nhfp, const char *name, unsigned long utdflags) critical_sizes[idx_1st_mismatch].ucsize, critical_sizes[idx_1st_mismatch].nm); } - return sfstatus; } Sfi_version_info(nhfp, &vers_info, "version_info"); if (!check_version(&vers_info, name, verbose, utdflags)) { if (verbose) { - if ((utdflags & UTD_WITHOUT_WAITSYNCH_PERFILE) == 0) + if ((utdflags & UTD_WITHOUT_WAITSYNCH_PERFILE) == 0) { wait_synch(); + } } return SF_OUTDATED; } - - return SF_UPTODATE; + return sfstatus; } /* @@ -819,12 +838,15 @@ validate(NHFILE *nhfp, const char *name, boolean without_waitsynch_perfile) unsigned long utdflags = 0L; int validsf = 0; +#ifdef SFCTOOL + utdflags |= UTD_QUIETLY; +#endif if (nhfp->structlevel) utdflags |= UTD_CHECKSIZES; if (without_waitsynch_perfile) utdflags |= UTD_WITHOUT_WAITSYNCH_PERFILE; if (nhfp->fieldlevel) - utdflags |= UTD_CHECKFIELDCOUNTS | UTD_SKIP_SANITY1 | UTD_QUIETLY; + utdflags |= UTD_CHECKFIELDCOUNTS | UTD_SKIP_SANITY1; validsf = uptodate(nhfp, name, utdflags); return validsf; } diff --git a/src/worm.c b/src/worm.c index af68084d1..e2bb61c3b 100644 --- a/src/worm.c +++ b/src/worm.c @@ -14,6 +14,7 @@ struct wseg { coordxy wx, wy; /* the segment's position */ }; +#ifndef SFCTOOL staticfn void toss_wsegs(struct wseg *, boolean) NO_NNARGS; staticfn void shrink_worm(int); @@ -21,6 +22,7 @@ staticfn void shrink_worm(int); staticfn void random_dir(int, int, int *, int *); #endif staticfn struct wseg *create_worm_tail(int); /* may return NULL */ +#endif /* !SFCTOOL */ /* Description of long worm implementation. * @@ -76,6 +78,7 @@ static struct wseg *wheads[MAX_NUM_WORMS] = DUMMY, *wtails[MAX_NUM_WORMS] = DUMMY; static long wgrowtime[MAX_NUM_WORMS] = DUMMY; +#ifndef SFCTOOL /* * get_wormno() * @@ -563,6 +566,7 @@ save_worm(NHFILE *nhfp) } } } +#endif /* !SFCTOOL */ /* * rest_worm() @@ -598,6 +602,7 @@ rest_worm(NHFILE *nhfp) } } +#ifndef SFCTOOL /* * place_wsegs() * @@ -991,5 +996,6 @@ redraw_worm(struct monst *worm) curr = curr->nseg; } } +#endif /* !SFCTOOL */ /*worm.c*/ diff --git a/sys/unix/Makefile.top b/sys/unix/Makefile.top index 9323f42c8..6e45eafa9 100644 --- a/sys/unix/Makefile.top +++ b/sys/unix/Makefile.top @@ -288,6 +288,11 @@ package: $(GAME) recover $(VARDAT) spec_levs recover: $(GAME) ( cd util ; $(MAKE) $(RECOVERBIN) ) +# sfctool can be configured by the sysadmin to convert the savefile +# content format as necessary. +sfctool: $(GAME) + ( cd util ; $(MAKE) sfctool ) + dofiles: target=`sed -n \ -e '/librarian/{' \ diff --git a/sys/unix/Makefile.utl b/sys/unix/Makefile.utl index 11a50aa1b..f402bf0c3 100644 --- a/sys/unix/Makefile.utl +++ b/sys/unix/Makefile.utl @@ -118,6 +118,12 @@ LIBS = OBJDIR = ../src +# This is the universal ctags utility which produces the tags in the +# format that util/readtags requires. +# https://github.com/universal-ctags/ctags.git +#CTAGSCMD = universal-ctags +CTAGSCMD = ctags + # if you change this to 1, feedback while building will omit -Dthis -Wthat # -Isomewhere so that each file being compiled is listed on one short line; # it requires support for '$<' in rules with more than one prerequisite @@ -288,6 +294,166 @@ recover.o: recover.c $(CONFIG_H) recover-version.o: ../src/version.c $(HACK_H) $(CC) $(CFLAGS) $(CSTD) -DMINIMAL_FOR_RECOVER -c ../src/version.c -o $@ +# +# dependencies for optional sfctool +# +# object files for sfctool utility +SFCTOOLOBJS = $(TARGETPFX)sfctool.o $(TARGETPFX)sf-alloc.o \ + $(TARGETPFX)sf-monst.o $(TARGETPFX)sf-objects.o \ + $(TARGETPFX)sfbase.o $(TARGETPFX)sfstruct.o \ + $(TARGETPFX)sfexpasc.o \ + $(TARGETPFX)sfdata.o $(TARGETPFX)sf-nhlua.o \ + $(TARGETPFX)panic.o $(TARGETPFX)sf-date.o \ + $(TARGETPFX)sf-decl.o $(TARGETPFX)sf-artifact.o \ + $(TARGETPFX)sf-dungeon.o $(TARGETPFX)sf-end.o \ + $(TARGETPFX)sf-engrave.o $(TARGETPFX)sf-cfgfiles.o \ + $(TARGETPFX)sf-files.o $(TARGETPFX)sf-light.o \ + $(TARGETPFX)sf-mdlib.o $(TARGETPFX)sf-mkmaze.o \ + $(TARGETPFX)sf-mkroom.o $(TARGETPFX)sf-o_init.o \ + $(TARGETPFX)sf-region.o $(TARGETPFX)sf-restore.o \ + $(TARGETPFX)sf-rumors.o $(TARGETPFX)sf-sys.o \ + $(TARGETPFX)sf-timeout.o $(TARGETPFX)sf-track.o \ + $(TARGETPFX)sf-version.o $(TARGETPFX)sf-worm.o \ + $(TARGETPFX)strutil.o +SFCTOOLBIN = sfctool + +SFFLAGS=-DSFCTOOL -DNOPANICTRACE -DNOCRASHREPORT -DNO_CHRONICLE +sfutil: $(SFCTOOLBIN) + @echo '$(SFCTOOLBIN) is up to date.' +$(SFCTOOLBIN): $(SFCTOOLOBJS) $(HACKLIB) + $(TARGET_CLINK) $(TARGET_LFLAGS) -o $@ $(SFCTOOLOBJS) $(HACKLIB) $(TARGET_LIBS) +$(TARGETPFX)sfctool.o: sfctool.c $(HACK_H) ../include/sfprocs.h + $(TARGET_CC) $(TARGET_CFLAGS) $(SFFLAGS) -o $@ -c sfctool.c +$(TARGETPFX)sfdata.o: sfdata.c $(HACK_H) ../include/sfprocs.h ../include/sfproto.h + $(TARGET_CC) $(TARGET_CFLAGS) $(SFFLAGS) -o $@ -c sfdata.c +$(TARGETPFX)sfexpasc.o: sfexpasc.c $(HACK_H) ../include/sfprocs.h ../include/sfproto.h + $(TARGET_CC) $(TARGET_CFLAGS) $(SFFLAGS) -o $@ -c sfexpasc.c +$(TARGETPFX)sf-alloc.o: ../src/alloc.c + $(TARGET_CC) $(TARGET_CFLAGS) $(SFFLAGS) -o $@ -c ../src/alloc.c +$(TARGETPFX)sf-date.o: ../src/date.c + $(TARGET_CC) $(TARGET_CFLAGS) $(SFFLAGS) -o $@ -c ../src/date.c +$(TARGETPFX)sf-decl.o: ../src/decl.c + $(TARGET_CC) $(TARGET_CFLAGS) $(SFFLAGS) -o $@ -c ../src/decl.c +$(TARGETPFX)sf-panic.o: panic.c $(CONFIG_H) + $(TARGET_CC) $(TARGET_CFLAGS) $(SFFLAGS) -o $@ -c panic.c +$(TARGETPFX)sf-monst.o: ../src/monst.c + $(TARGET_CC) $(TARGET_CFLAGS) $(SFFLAGS) -o $@ -c ../src/monst.c +$(TARGETPFX)sf-objects.o: ../src/objects.c + $(TARGET_CC) $(TARGET_CFLAGS) $(SFFLAGS) -o $@ -c ../src/objects.c +$(TARGETPFX)sf-sfbase.o: ../src/sfbase.c + $(TARGET_CC) $(TARGET_CFLAGS) $(SFFLAGS) -o $@ -c ../src/sfbase.c +$(TARGETPFX)sfstruct.o: ../src/sfstruct.c + $(TARGET_CC) $(TARGET_CFLAGS) $(SFFLAGS) -o $@ -c ../src/sfstruct.c +$(TARGETPFX)sf-artifact.o: ../src/artifact.c + $(TARGET_CC) $(TARGET_CFLAGS) $(SFFLAGS) -o $@ -c ../src/artifact.c +$(TARGETPFX)sf-dungeon.o: ../src/dungeon.c + $(TARGET_CC) $(TARGET_CFLAGS) $(SFFLAGS) -o $@ -c ../src/dungeon.c +$(TARGETPFX)sf-end.o: ../src/end.c + $(TARGET_CC) $(TARGET_CFLAGS) $(SFFLAGS) -o $@ -c ../src/end.c +$(TARGETPFX)sf-engrave.o: ../src/engrave.c + $(TARGET_CC) $(TARGET_CFLAGS) $(SFFLAGS) -o $@ -c ../src/engrave.c +$(TARGETPFX)sf-cfgfiles.o: ../src/cfgfiles.c + $(TARGET_CC) $(TARGET_CFLAGS) $(SFFLAGS) -o $@ -c ../src/cfgfiles.c +$(TARGETPFX)sf-files.o: ../src/files.c + $(TARGET_CC) $(TARGET_CFLAGS) $(SFFLAGS) -o $@ -c ../src/files.c +$(TARGETPFX)sf-light.o: ../src/light.c + $(TARGET_CC) $(TARGET_CFLAGS) $(SFFLAGS) -o $@ -c ../src/light.c +$(TARGETPFX)sf-mdlib.o: ../src/mdlib.c + $(TARGET_CC) $(TARGET_CFLAGS) $(SFFLAGS) -o $@ -c ../src/mdlib.c +$(TARGETPFX)sf-mkmaze.o: ../src/mkmaze.c + $(TARGET_CC) $(TARGET_CFLAGS) $(SFFLAGS) -o $@ -c ../src/mkmaze.c +$(TARGETPFX)sf-mkroom.o: ../src/mkroom.c + $(TARGET_CC) $(TARGET_CFLAGS) $(SFFLAGS) -o $@ -c ../src/mkroom.c +$(TARGETPFX)sf-o_init.o: ../src/o_init.c + $(TARGET_CC) $(TARGET_CFLAGS) $(SFFLAGS) -o $@ -c ../src/o_init.c +$(TARGETPFX)sf-region.o: ../src/region.c + $(TARGET_CC) $(TARGET_CFLAGS) $(SFFLAGS) -o $@ -c ../src/region.c +$(TARGETPFX)sf-restore.o: ../src/restore.c + $(TARGET_CC) $(TARGET_CFLAGS) $(SFFLAGS) -o $@ -c ../src/restore.c +$(TARGETPFX)sf-rumors.o: ../src/rumors.c + $(TARGET_CC) $(TARGET_CFLAGS) $(SFFLAGS) -o $@ -c ../src/rumors.c +$(TARGETPFX)sf-sys.o: ../src/sys.c + $(TARGET_CC) $(TARGET_CFLAGS) $(SFFLAGS) -o $@ -c ../src/sys.c +$(TARGETPFX)sf-timeout.o: ../src/timeout.c + $(TARGET_CC) $(TARGET_CFLAGS) $(SFFLAGS) -o $@ -c ../src/timeout.c +$(TARGETPFX)sf-track.o: ../src/track.c + $(TARGET_CC) $(TARGET_CFLAGS) $(SFFLAGS) -o $@ -c ../src/track.c +$(TARGETPFX)sf-version.o: ../src/version.c + $(TARGET_CC) $(TARGET_CFLAGS) $(SFFLAGS) -o $@ -c ../src/version.c +$(TARGETPFX)sf-worm.o: ../src/worm.c + $(TARGET_CC) $(TARGET_CFLAGS) $(SFFLAGS) -o $@ -c ../src/worm.c +$(TARGETPFX)sf-nhlua.o: ../src/nhlua.c + $(TARGET_CC) $(TARGET_CFLAGS) $(SFFLAGS) -o $@ -c ../src/nhlua.c +$(TARGETPFX)sfbase.o: ../src/sfbase.c + $(TARGET_CC) $(TARGET_CFLAGS) $(SFFLAGS) -o $@ -c ../src/sfbase.c +$(TARGETPFX)strutil.o: ../src/strutil.c + $(TARGET_CC) $(TARGET_CFLAGS) $(SFFLAGS) -o $@ -c ../src/strutil.c + +sftags: sftags.o + $(CLINK) $(LFLAGS) -o $@ sftags.o $(LIBS) +sftags.o: sftags.c $(HACK_H) + $(CC) $(CFLAGS) -c sftags.c +../include/sfproto.h: sf.tags sftags + ./sftags +sfdata.c: sf.tags sftags + ./sftags +# dependencies for sftags +# # +CTAGDEP = ../include/align.h ../include/artifact.h ../include/artilist.h \ + ../include/attrib.h ../include/context.h ../include/coord.h \ + ../include/decl.h ../include/dungeon.h ../include/engrave.h \ + ../include/flag.h ../include/func_tab.h ../include/global.h \ + ../include/hack.h ../include/mextra.h \ + ../include/mkroom.h ../include/monst.h ../include/defsym.h \ + ../include/obj.h ../include/objclass.h ../include/prop.h \ + ../include/quest.h ../include/rect.h ../include/region.h \ + ../include/rm.h ../include/skills.h ../include/spell.h \ + ../include/sys.h ../include/timeout.h ../include/trap.h \ + ../include/you.h ../include/onames.h ../include/wintype.h +# ../include/permonst.h +CTAGSOPT = --language-force=c --sort=no -D"Bitfield(x,n)=unsigned x : n" --excmd=pattern +# +INCL=../include/ +SRC=../src/ +sf.tags: $(CTAGDEP) + $(CTAGSCMD) $(CTAGSOPT) -f $@ $(INCL)align.h + $(CTAGSCMD) $(CTAGSOPT) -a -f $@ $(INCL)artifact.h + $(CTAGSCMD) $(CTAGSOPT) -a -f $@ $(SRC)artifact.c + $(CTAGSCMD) $(CTAGSOPT) -a -f $@ $(INCL)artilist.h + $(CTAGSCMD) $(CTAGSOPT) -a -f $@ $(INCL)attrib.h + $(CTAGSCMD) $(CTAGSOPT) -a -f $@ $(SRC)bones.c + $(CTAGSCMD) $(CTAGSOPT) -a -f $@ $(INCL)context.h + $(CTAGSCMD) $(CTAGSOPT) -a -f $@ $(INCL)coord.h + $(CTAGSCMD) $(CTAGSOPT) -a -f $@ $(INCL)decl.h + $(CTAGSCMD) $(CTAGSOPT) -a -f $@ $(SRC)decl.c + $(CTAGSCMD) $(CTAGSOPT) -a -f $@ $(INCL)dungeon.h + $(CTAGSCMD) $(CTAGSOPT) -a -f $@ $(INCL)engrave.h + $(CTAGSCMD) $(CTAGSOPT) -a -f $@ $(SRC)engrave.c + $(CTAGSCMD) $(CTAGSOPT) -a -f $@ $(INCL)flag.h + $(CTAGSCMD) $(CTAGSOPT) -a -f $@ $(INCL)func_tab.h + $(CTAGSCMD) $(CTAGSOPT) -a -f $@ $(INCL)global.h + $(CTAGSCMD) $(CTAGSOPT) -a -f $@ $(INCL)hack.h + $(CTAGSCMD) $(CTAGSOPT) -a -f $@ $(INCL)mextra.h + $(CTAGSCMD) $(CTAGSOPT) -a -f $@ $(INCL)mkroom.h + $(CTAGSCMD) $(CTAGSOPT) -a -f $@ $(INCL)monst.h + $(CTAGSCMD) $(CTAGSOPT) -a -f $@ $(INCL)defsym.h + $(CTAGSCMD) $(CTAGSOPT) -a -f $@ $(INCL)obj.h + $(CTAGSCMD) $(CTAGSOPT) -a -f $@ $(INCL)objclass.h +# $(CTAGSCMD) $(CTAGSOPT) -a -f $@ $(INCL)permonst.h + $(CTAGSCMD) $(CTAGSOPT) -a -f $@ $(INCL)prop.h + $(CTAGSCMD) $(CTAGSOPT) -a -f $@ $(INCL)quest.h + $(CTAGSCMD) $(CTAGSOPT) -a -f $@ $(INCL)rect.h + $(CTAGSCMD) $(CTAGSOPT) -a -f $@ $(INCL)region.h + $(CTAGSCMD) $(CTAGSOPT) -a -f $@ $(INCL)rm.h + $(CTAGSCMD) $(CTAGSOPT) -a -f $@ $(INCL)skills.h + $(CTAGSCMD) $(CTAGSOPT) -a -f $@ $(INCL)spell.h + $(CTAGSCMD) $(CTAGSOPT) -a -f $@ $(INCL)stairs.h + $(CTAGSCMD) $(CTAGSOPT) -a -f $@ $(INCL)sys.h + $(CTAGSCMD) $(CTAGSOPT) -a -f $@ $(INCL)timeout.h + $(CTAGSCMD) $(CTAGSOPT) -a -f $@ $(INCL)trap.h + $(CTAGSCMD) $(CTAGSOPT) -a -f $@ $(INCL)you.h + $(CTAGSCMD) $(CTAGSOPT) -a -f $@ $(INCL)onames.h + $(CTAGSCMD) $(CTAGSOPT) -a -f $@ $(INCL)wintype.h # dependencies for dlb # diff --git a/sys/unix/hints/include/cross-post.370 b/sys/unix/hints/include/cross-post.370 index 3e9a9cd39..9d7c5b548 100644 --- a/sys/unix/hints/include/cross-post.370 +++ b/sys/unix/hints/include/cross-post.370 @@ -49,6 +49,7 @@ dospkg: dodata dosfonts $(GAMEBIN) $(TARGETPFX)recover.exe ../dat/nhtiles.bmp mkdir -p $(TARGETPFX)pkg cp $(GAMEBIN) $(TARGETPFX)pkg/NETHACK.EXE cp $(TARGETPFX)recover.exe $(TARGETPFX)pkg/RECOVER.EXE + -cp $(SFCTOOLBIN) $(TARGETPFX)pkg/SFCTOOL.EXE cp ../dat/nhdat $(TARGETPFX)pkg/NHDAT cp ../dat/license $(TARGETPFX)pkg/LICENSE cp ../dat/nhtiles.bmp $(TARGETPFX)pkg/NHTILES.BMP diff --git a/sys/unix/hints/include/cross-pre2.370 b/sys/unix/hints/include/cross-pre2.370 index 9730be4da..df4ef6105 100644 --- a/sys/unix/hints/include/cross-pre2.370 +++ b/sys/unix/hints/include/cross-pre2.370 @@ -228,6 +228,7 @@ override LUALIBS= override TOPLUALIB= override GAMEBIN = $(TARGETPFX)nethack.exe override RECOVERBIN = $(TARGETPFX)recover.exe +override SFCTOOLBIN = $(TARGETPFX)sfctool.exe override PACKAGE = dospkg override PREGAME += mkdir -p $(TARGETDIR) ; make $(TARGETPFX)exceptn.o ; override CLEANMORE += rm -f -r $(TARGETDIR) ; rm -f -r $(FONTTARGETS) ; diff --git a/sys/windows/Makefile.nmake b/sys/windows/Makefile.nmake index c3daf54df..8f19c209c 100644 --- a/sys/windows/Makefile.nmake +++ b/sys/windows/Makefile.nmake @@ -866,15 +866,15 @@ COREOBJTTY = \ $(OTTY)quest.o $(OTTY)questpgr.o $(OTTY)read.o $(OTTY)rect.o \ $(OTTY)region.o $(OTTY)report.o $(OTTY)restore.o $(OTTY)rip.o \ $(OTTY)rnd.o $(OTTY)role.o $(OTTY)rumors.o $(OTTY)save.o \ - $(OTTY)selvar.o $(OTTY)sfstruct.o $(OTTY)shk.o $(OTTY)shknam.o \ - $(OTTY)sit.o $(OTTY)sounds.o $(OTTY)sp_lev.o $(OTTY)spell.o \ - $(OTTY)stairs.o $(OTTY)steal.o $(OTTY)steed.o $(OTTY)strutil.o \ - $(OTTY)symbols.o $(OTTY)sys.o $(OTTY)teleport.o $(OTTY)timeout.o \ - $(OTTY)topten.o $(OTTY)track.o $(OTTY)trap.o $(OTTY)u_init.o \ - $(OTTY)uhitm.o $(OTTY)utf8map.o $(OTTY)vault.o $(OTTY)vision.o \ - $(OTTY)weapon.o $(OTTY)were.o $(OTTY)wield.o $(OTTY)windows.o \ - $(OTTY)wizard.o $(OTTY)wizcmds.o $(OTTY)worm.o $(OTTY)worn.o \ - $(OTTY)write.o $(OTTY)zap.o $(OTTY)sfbase.o + $(OTTY)selvar.o $(OTTY)sfbase.o $(OTTY)sfstruct.o $(OTTY)shk.o \ + $(OTTY)shknam.o $(OTTY)sit.o $(OTTY)sounds.o $(OTTY)sp_lev.o \ + $(OTTY)spell.o $(OTTY)stairs.o $(OTTY)steal.o $(OTTY)steed.o \ + $(OTTY)strutil.o $(OTTY)symbols.o $(OTTY)sys.o $(OTTY)teleport.o \ + $(OTTY)timeout.o $(OTTY)topten.o $(OTTY)track.o $(OTTY)trap.o \ + $(OTTY)u_init.o $(OTTY)uhitm.o $(OTTY)utf8map.o $(OTTY)vault.o \ + $(OTTY)vision.o $(OTTY)weapon.o $(OTTY)were.o $(OTTY)wield.o \ + $(OTTY)windows.o $(OTTY)wizard.o $(OTTY)wizcmds.o $(OTTY)worm.o \ + $(OTTY)worn.o $(OTTY)write.o $(OTTY)zap.o OBJSTTY = $(MDLIBTTY) $(COREOBJTTY) $(REGEXTTY) $(RANDOMTTY) @@ -929,15 +929,15 @@ COREOBJGUI = \ $(OGUI)quest.o $(OGUI)questpgr.o $(OGUI)read.o $(OGUI)rect.o \ $(OGUI)region.o $(OGUI)report.o $(OGUI)restore.o $(OGUI)rip.o \ $(OGUI)rnd.o $(OGUI)role.o $(OGUI)rumors.o $(OGUI)save.o \ - $(OGUI)selvar.o $(OGUI)sfstruct.o $(OGUI)shk.o $(OGUI)shknam.o \ - $(OGUI)sit.o $(OGUI)sounds.o $(OGUI)sp_lev.o $(OGUI)spell.o \ - $(OGUI)stairs.o $(OGUI)steal.o $(OGUI)steed.o $(OGUI)strutil.o \ - $(OGUI)symbols.o $(OGUI)sys.o $(OGUI)teleport.o $(OGUI)timeout.o \ - $(OGUI)topten.o $(OGUI)track.o $(OGUI)trap.o $(OGUI)u_init.o \ - $(OGUI)uhitm.o $(OGUI)utf8map.o $(OGUI)vault.o $(OGUI)vision.o \ - $(OGUI)weapon.o $(OGUI)were.o $(OGUI)wield.o $(OGUI)windows.o \ - $(OGUI)wizard.o $(OGUI)wizcmds.o $(OGUI)worm.o $(OGUI)worn.o \ - $(OGUI)write.o $(OGUI)zap.o $(OGUI)sfbase.o + $(OGUI)selvar.o $(OGUI)sfbase.o $(OGUI)sfstruct.o $(OGUI)shk.o \ + $(OGUI)shknam.o $(OGUI)sit.o $(OGUI)sounds.o $(OGUI)sp_lev.o \ + $(OGUI)spell.o $(OGUI)stairs.o $(OGUI)steal.o $(OGUI)steed.o \ + $(OGUI)strutil.o $(OGUI)symbols.o $(OGUI)sys.o $(OGUI)teleport.o \ + $(OGUI)timeout.o $(OGUI)topten.o $(OGUI)track.o $(OGUI)trap.o \ + $(OGUI)u_init.o $(OGUI)uhitm.o $(OGUI)utf8map.o $(OGUI)vault.o \ + $(OGUI)vision.o $(OGUI)weapon.o $(OGUI)were.o $(OGUI)wield.o \ + $(OGUI)windows.o $(OGUI)wizard.o $(OGUI)wizcmds.o $(OGUI)worm.o \ + $(OGUI)worn.o $(OGUI)write.o $(OGUI)zap.o OBJSGUI = $(MDLIBGUI) $(COREOBJGUI) $(REGEXGUI) $(RANDOMGUI) @@ -1155,7 +1155,7 @@ R_CTAGSDIR=$(LIBDIR)ctags CTAGSDIR=$(R_CTAGSDIR)$(BACKSLASH) #U_CTAGSDIR=$(CTAGSDIR:\=/) !ELSE -R_CTAGSDIR=..\..\..\ctags +R_CTAGSDIR=..\lib\ctags CTAGSDIR=$(R_CTAGSDIR)$(BACKSLASH) #U_CTAGSDIR=$(CTAGSDIR:\=/) !ENDIF @@ -1724,6 +1724,7 @@ binary.tag: $(DAT)data $(DAT)rumors $(DAT)oracles $(DLB) \ if exist $(DAT)symbols copy $(DAT)symbols $(GAMEDIR)symbols if exist $(DOC)guidebook.txt copy $(DOC)guidebook.txt $(GAMEDIR)Guidebook.txt if exist $(DOC)nethack.txt copy $(DOC)nethack.txt $(GAMEDIR)NetHack.txt +# if exist $(UTIL)sfctool.pdb copy $(UTIL)sfctool.pdb $(GAMEDIR)sfctool.pdb @if exist $(GAMEDIR)NetHack.PDB echo NOTE: You may want to remove $(U_GAMEDIR)/NetHack.PDB to conserve space @if exist $(GAMEDIR)NetHackW.PDB echo NOTE: You may want to remove $(U_GAMEDIR)/NetHackW.PDB to conserve space -if exist $(MSWSYS)nethackrc.template copy $(MSWSYS)nethackrc.template $(R_GAMEDIR) @@ -2471,6 +2472,174 @@ $(DAT)epitaph: $(U)makedefs.exe $(DAT)epitaph.txt $(DAT)bogusmon: $(U)makedefs.exe $(DAT)bogusmon.txt $(U)makedefs -3 +# This is the universal ctags utility which produces the tags in the +# format that util/readtags requires. +# https://github.com/universal-ctags/ctags.git + +#=============================================================================== +# sfutil +#=============================================================================== +SFCTOOLOBJS = $(OUTL)sfctool.o $(OUTL)sf-alloc.o \ + $(OUTL)sf-monst.o $(OUTL)sf-objects.o \ + $(OUTL)sfbase.o $(OUTL)sf-struct.o \ + $(OUTL)sfexpasc.o \ + $(OUTL)sfdata.o $(OUTL)sf-nhlua.o \ + $(OUTL)panic.o $(OUTL)sf-date.o $(OUTL)sf-decl.o \ + $(OUTL)sf-artifact.o $(OUTL)sf-cfgfiles.o \ + $(OUTL)sf-dungeon.o $(OUTL)sf-end.o \ + $(OUTL)sf-engrave.o $(OUTL)sf-files.o $(OUTL)sf-light.o \ + $(OUTL)sf-mdlib.o $(OUTL)sf-mkmaze.o $(OUTL)sf-mkroom.o \ + $(OUTL)sf-o_init.o $(OUTL)sf-region.o \ + $(OUTL)sf-restore.o $(OUTL)sf-rumors.o \ + $(OUTL)sf-sys.o $(OUTL)sf-timeout.o $(OUTL)sf-track.o \ + $(OUTL)sf-version.o $(OUTL)sf-worm.o \ + $(OUTL)strutil.o $(OUTL)sf-windsys.o + +SFCTOOLBIN = $(BinDir)sfctool.exe +SFFLAGS = -DSFCTOOL -DNOPANICTRACE -DNOCRASHREPORT -DNO_CHRONICLE + +#CTAGSCMD = $(LIB)\ctags\ctags.exe + +# +# dependencies for optional sfctool +# +# $(Q)$(CC) $(CFLAGS) -Fo$@ monst.c + +#$(UTIL)sfutil.exe: $(SFCTOOLBIN) +#$(UTIL)sfctool.exe: $(SFCTOOLBIN) + +$(SFCTOOLBIN): $(OUTLHACKLIB) $(SFCTOOLOBJS) + $(link) $(lflags) -out:$@ /PDB:$(BinDir)$(@B).PDB $(SFCTOOLOBJS) \ + $(LIBS) ole32.lib Shell32.lib userenv.lib advapi32.lib $(OUTLHACKLIB) + @echo '$(SFCTOOLBIN) is up to date.' +$(OUTL)sfctool.o: $(UTIL)sfctool.c $(HACK_H) $(INCL)sfprocs.h + $(Q)$(CC) $(CFLAGS) $(SFFLAGS) -Fo$@ -c $(UTIL)sfctool.c +$(OUTL)sfdata.o: $(UTIL)sfdata.c $(HACK_H) $(INCL)sfprocs.h $(INCL)sfproto.h + $(Q)$(CC) $(CFLAGS) $(SFFLAGS) -Fo$@ -c $(UTIL)sfdata.c +$(OUTL)sfexpasc.o: $(UTIL)sfexpasc.c $(HACK_H) $(INCL)sfprocs.h $(INCL)sfproto.h + $(Q)$(CC) $(CFLAGS) $(SFFLAGS) -Fo$@ -c $(UTIL)sfexpasc.c +$(OUTL)sf-alloc.o: $(SRC)alloc.c + $(Q)$(CC) $(CFLAGS) $(SFFLAGS) -Fo$@ -c $(SRC)alloc.c +$(OUTL)sf-date.o: $(SRC)date.c + $(Q)$(CC) $(CFLAGS) $(SFFLAGS) -Fo$@ -c $(SRC)date.c +$(OUTL)sf-decl.o: $(SRC)decl.c + $(Q)$(CC) $(CFLAGS) $(SFFLAGS) -Fo$@ -c $(SRC)decl.c +$(OUTL)sf-monst.o: $(SRC)monst.c + $(Q)$(CC) $(CFLAGS) $(SFFLAGS) -Fo$@ -c $(SRC)monst.c +$(OUTL)sf-objects.o: $(SRC)objects.c + $(Q)$(CC) $(CFLAGS) $(SFFLAGS) -Fo$@ -c $(SRC)objects.c +$(OUTL)sfbase.o: $(SRC)sfbase.c + $(Q)$(CC) $(CFLAGS) $(SFFLAGS) -Fo$@ -c $(SRC)sfbase.c +$(OUTL)sf-struct.o: $(SRC)sfstruct.c + $(Q)$(CC) $(CFLAGS) $(SFFLAGS) -Fo$@ -c $(SRC)sfstruct.c +$(OUTL)sf-artifact.o: $(SRC)artifact.c + $(Q)$(CC) $(CFLAGS) $(SFFLAGS) -Fo$@ -c $(SRC)artifact.c +$(OUTL)sf-cfgfiles.o: $(SRC)cfgfiles.c + $(Q)$(CC) $(CFLAGS) $(SFFLAGS) -Fo$@ -c $(SRC)cfgfiles.c +$(OUTL)sf-dungeon.o: $(SRC)dungeon.c + $(Q)$(CC) $(CFLAGS) $(SFFLAGS) -Fo$@ -c $(SRC)dungeon.c +$(OUTL)sf-end.o: $(SRC)end.c + $(Q)$(CC) $(CFLAGS) $(SFFLAGS) -Fo$@ -c $(SRC)end.c +$(OUTL)sf-engrave.o: $(SRC)engrave.c + $(Q)$(CC) $(CFLAGS) $(SFFLAGS) -Fo$@ -c $(SRC)engrave.c +$(OUTL)sf-files.o: $(SRC)files.c + $(Q)$(CC) $(CFLAGS) $(SFFLAGS) -Fo$@ -c $(SRC)files.c +$(OUTL)sf-light.o: $(SRC)light.c + $(Q)$(CC) $(CFLAGS) $(SFFLAGS) -Fo$@ -c $(SRC)light.c +$(OUTL)sf-mdlib.o: $(SRC)mdlib.c + $(Q)$(CC) $(CFLAGS) $(SFFLAGS) -Fo$@ -c $(SRC)mdlib.c +$(OUTL)sf-mkmaze.o: $(SRC)mkmaze.c + $(Q)$(CC) $(CFLAGS) $(SFFLAGS) -Fo$@ -c $(SRC)mkmaze.c +$(OUTL)sf-mkroom.o: $(SRC)mkroom.c + $(Q)$(CC) $(CFLAGS) $(SFFLAGS) -Fo$@ -c $(SRC)mkroom.c +$(OUTL)sf-o_init.o: $(SRC)o_init.c + $(Q)$(CC) $(CFLAGS) $(SFFLAGS) -Fo$@ -c $(SRC)o_init.c +$(OUTL)sf-region.o: $(SRC)region.c + $(Q)$(CC) $(CFLAGS) $(SFFLAGS) -Fo$@ -c $(SRC)region.c +$(OUTL)sf-restore.o: $(SRC)restore.c + $(Q)$(CC) $(CFLAGS) $(SFFLAGS) -Fo$@ -c $(SRC)restore.c +$(OUTL)sf-rumors.o: $(SRC)\rumors.c + $(Q)$(CC) $(CFLAGS) $(SFFLAGS) -Fo$@ -c $(SRC)rumors.c +$(OUTL)sf-timeout.o: $(SRC)timeout.c + $(Q)$(CC) $(CFLAGS) $(SFFLAGS) -Fo$@ -c $(SRC)timeout.c +$(OUTL)sf-version.o: $(SRC)version.c + $(Q)$(CC) $(CFLAGS) $(SFFLAGS) -Fo$@ -c $(SRC)version.c +$(OUTL)sf-worm.o: $(SRC)worm.c + $(Q)$(CC) $(CFLAGS) $(SFFLAGS) -Fo$@ -c $(SRC)worm.c +$(OUTL)sf-nhlua.o: $(SRC)nhlua.c + $(Q)$(CC) $(CFLAGS) $(SFFLAGS) -Fo$@ -c $(SRC)nhlua.c +$(OUTL)sf-track.o: $(SRC)track.c + $(Q)$(CC) $(CFLAGS) $(SFFLAGS) -Fo$@ -c $(SRC)track.c +$(OUTL)sf-sys.o: $(SRC)sys.c + $(Q)$(CC) $(CFLAGS) $(SFFLAGS) -Fo$@ -c $(SRC)sys.c +$(OUTL)sf-windsys.o: $(MSWSYS)windsys.c + $(Q)$(CC) $(CFLAGS) $(SFFLAGS) -Fo$@ -c $(MSWSYS)windsys.c + +$(UTIL)sftags.exe: $(OUTL)sftags.o + $(link) $(LFLAGS) /OUT:$@ $(OUTL)sftags.o +$(OUTL)sftags.o: $(UTIL)sftags.c $(HACK_H) + $(Q)$(CC) $(CFLAGS) -Fo$@ -c $(UTIL)sftags.c +$(INCL)sfproto.h: $(UTIL)sftags.exe $(UTIL)sf.tags + $(UTIL)sftags.exe +$(UTIL)sfdata.c: $(UTIL)sftags.exe $(UTIL)sf.tags + $(UTIL)sftags.exe +# dependencies for sftags +# # +CTAGDEP = $(INCL)align.h $(INCL)artifact.h $(INCL)artilist.h \ + $(INCL)attrib.h $(INCL)context.h $(INCL)coord.h \ + $(INCL)decl.h $(INCL)dungeon.h $(INCL)engrave.h \ + $(INCL)flag.h $(INCL)func_tab.h $(INCL)global.h \ + $(INCL)hack.h $(INCL)mextra.h \ + $(INCL)mkroom.h $(INCL)monst.h \ + $(INCL)obj.h $(INCL)objclass.h $(INCL)prop.h \ + $(INCL)quest.h $(INCL)rect.h $(INCL)region.h \ + $(INCL)rm.h $(INCL)skills.h $(INCL)spell.h \ + $(INCL)stairs.h $(INCL)sys.h $(INCL)timeout.h \ + $(INCL)trap.h $(INCL)you.h $(INCL)onames.h \ + $(INCL)wintype.h +# $(INCL)permonst.h +CTAGSOPT = --language-force=c --sort=no -D"Bitfield(x,n)=unsigned x : n" --excmd=pattern +# +$(UTIL)sf.tags: $(CTAGDEP) + $(CTAGSCMD) $(CTAGSOPT) -f $@ $(INCL)align.h + $(CTAGSCMD) $(CTAGSOPT) -a -f $@ $(INCL)artifact.h + $(CTAGSCMD) $(CTAGSOPT) -a -f $@ $(SRC)artifact.c + $(CTAGSCMD) $(CTAGSOPT) -a -f $@ $(INCL)artilist.h + $(CTAGSCMD) $(CTAGSOPT) -a -f $@ $(INCL)attrib.h + $(CTAGSCMD) $(CTAGSOPT) -a -f $@ $(SRC)bones.c + $(CTAGSCMD) $(CTAGSOPT) -a -f $@ $(INCL)context.h + $(CTAGSCMD) $(CTAGSOPT) -a -f $@ $(INCL)coord.h + $(CTAGSCMD) $(CTAGSOPT) -a -f $@ $(INCL)decl.h + $(CTAGSCMD) $(CTAGSOPT) -a -f $@ $(SRC)decl.c + $(CTAGSCMD) $(CTAGSOPT) -a -f $@ $(INCL)dungeon.h + $(CTAGSCMD) $(CTAGSOPT) -a -f $@ $(INCL)engrave.h + $(CTAGSCMD) $(CTAGSOPT) -a -f $@ $(SRC)engrave.c + $(CTAGSCMD) $(CTAGSOPT) -a -f $@ $(INCL)flag.h + $(CTAGSCMD) $(CTAGSOPT) -a -f $@ $(INCL)func_tab.h + $(CTAGSCMD) $(CTAGSOPT) -a -f $@ $(INCL)global.h + $(CTAGSCMD) $(CTAGSOPT) -a -f $@ $(INCL)hack.h + $(CTAGSCMD) $(CTAGSOPT) -a -f $@ $(INCL)mextra.h + $(CTAGSCMD) $(CTAGSOPT) -a -f $@ $(INCL)mkroom.h + $(CTAGSCMD) $(CTAGSOPT) -a -f $@ $(INCL)monst.h + $(CTAGSCMD) $(CTAGSOPT) -a -f $@ $(INCL)defsym.h + $(CTAGSCMD) $(CTAGSOPT) -a -f $@ $(INCL)obj.h + $(CTAGSCMD) $(CTAGSOPT) -a -f $@ $(INCL)objclass.h +# $(CTAGSCMD) $(CTAGSOPT) -a -f $@ $(INCL)permonst.h + $(CTAGSCMD) $(CTAGSOPT) -a -f $@ $(INCL)prop.h + $(CTAGSCMD) $(CTAGSOPT) -a -f $@ $(INCL)quest.h + $(CTAGSCMD) $(CTAGSOPT) -a -f $@ $(INCL)rect.h + $(CTAGSCMD) $(CTAGSOPT) -a -f $@ $(INCL)region.h + $(CTAGSCMD) $(CTAGSOPT) -a -f $@ $(INCL)rm.h + $(CTAGSCMD) $(CTAGSOPT) -a -f $@ $(INCL)skills.h + $(CTAGSCMD) $(CTAGSOPT) -a -f $@ $(INCL)spell.h + $(CTAGSCMD) $(CTAGSOPT) -a -f $@ $(INCL)stairs.h + $(CTAGSCMD) $(CTAGSOPT) -a -f $@ $(INCL)sys.h + $(CTAGSCMD) $(CTAGSOPT) -a -f $@ $(INCL)timeout.h + $(CTAGSCMD) $(CTAGSOPT) -a -f $@ $(INCL)trap.h + $(CTAGSCMD) $(CTAGSOPT) -a -f $@ $(INCL)you.h + $(CTAGSCMD) $(CTAGSOPT) -a -f $@ $(INCL)onames.h + $(CTAGSCMD) $(CTAGSOPT) -a -f $@ $(INCL)wintype.h + #=============================================================================== # Integrated sound files #=============================================================================== @@ -2541,13 +2710,15 @@ $(SndWavDir)sa2_xplevelup.wav: $(SndWavDir)sa2_xplevelup.uu $(U)uudecode.exe #=============================================================================== PKGFILES = nethackrc.template Guidebook.txt license NetHack.exe NetHack.txt \ - NetHackW.exe opthelp nhdat370 record symbols sysconf.template + NetHackW.exe opthelp nhdat370 record symbols sysconf.template \ + sfctool.exe FILESTOZIP = $(BinDir)nethackrc.template $(BinDir)Guidebook.txt $(BinDir)license \ $(BinDir)NetHack.exe $(BinDir)NetHack.txt $(BinDir)NetHackW.exe \ $(BinDir)opthelp $(BinDir)nhdat370 $(BinDir)record \ - $(BinDir)symbols $(BinDir)sysconf.template -DBGSYMS = NetHack.PDB NetHackW.PDB -PDBTOZIP = $(BinDir)NetHack.PDB $(BinDir)NetHackW.PDB + $(BinDir)symbols $(BinDir)sysconf.template $(BinDir)sfctool.exe + +DBGSYMS = NetHack.PDB NetHackW.PDB sfctool.PDB +PDBTOZIP = $(BinDir)NetHack.PDB $(BinDir)NetHackW.PDB $(BinDir)sfctool.PDB MAINZIP = $(PkgDir)nethack-$(NHV)-win-$(TARGET_CPU).zip DBGSYMZIP = $(PkgDir)nethack-$(NHV)-win-$(TARGET_CPU)-debugsymbols.zip @@ -2568,7 +2739,7 @@ binary: envchk.tag libdir.tag ottydir$(TARGET_CPU).tag \ $(INCL)nhlua.h $(OUTL)utility.tag \ $(DAT)data $(DAT)rumors $(DAT)oracles $(DAT)engrave \ $(DAT)epitaph $(DAT)bogusmon $(GAMEDIR)NetHack.exe \ - $(GAMEDIR)NetHackW.exe $(GAMEDIRDLLS) binary.tag + $(GAMEDIR)NetHackW.exe $(GAMEDIR)sfctool.exe $(GAMEDIRDLLS) binary.tag @echo NetHack is up to date. #=============================================================================== diff --git a/sys/windows/vs/NetHack/NetHack.vcxproj b/sys/windows/vs/NetHack/NetHack.vcxproj index bdc5d771f..002d5c9be 100644 --- a/sys/windows/vs/NetHack/NetHack.vcxproj +++ b/sys/windows/vs/NetHack/NetHack.vcxproj @@ -317,4 +317,4 @@ - \ No newline at end of file + diff --git a/sys/windows/vs/NetHackW/NetHackW.vcxproj b/sys/windows/vs/NetHackW/NetHackW.vcxproj index 5ba44b3dc..8db832c65 100644 --- a/sys/windows/vs/NetHackW/NetHackW.vcxproj +++ b/sys/windows/vs/NetHackW/NetHackW.vcxproj @@ -379,4 +379,4 @@ - \ No newline at end of file + diff --git a/sys/windows/vs/dirs.props b/sys/windows/vs/dirs.props index dc3f7ca7b..8f1f17062 100644 --- a/sys/windows/vs/dirs.props +++ b/sys/windows/vs/dirs.props @@ -29,6 +29,8 @@ $(RootDir)win\curses\ $(RootDir)submodules\ $(LibDir)lua-$(LUA_VERSION)\src\ + $(RootDir)\sys\windows\vs\sftags\ + $(RootDir)\sys\windows\vs\sfctool\ $(LibDir)pdcursesmod\ diff --git a/sys/windows/vs/fetchctags/fetchctags.nmake b/sys/windows/vs/fetchctags/fetchctags.nmake new file mode 100644 index 000000000..70023ce1d --- /dev/null +++ b/sys/windows/vs/fetchctags/fetchctags.nmake @@ -0,0 +1,49 @@ +# NetHack 3.7 fetchctags.nmake +#============================================================================== +# +# The version of the game this Makefile was designed for +NETHACK_VERSION="3.7.0" + +# A brief version for use in macros +NHV=$(NETHACK_VERSION:.=) +NHV=$(NHV:"=) + +# The location of the ctags that we want +CTAGS_VERSION=6.1.0 +CURLCTAGSSRC=https://github.com/universal-ctags/ctags-win32/releases/download/v$(CTAGS_VERSION)/ctags-v$(CTAGS_VERSION)-x64.zip +CURLCTAGSDST=ctags-v$(CTAGS_VERSION)-x64.zip + +# +# relative directories from root of NetHack tree. +# + +ROOTDIR=..\..\..\.. # root of NetHack tree relative to project file +LIBDIR=$(ROOTDIR)\lib +CTAGSDIR=$(LIBDIR)\ctags + +default: fetchall + +fetchall: fetch-ctags + +fetch-ctags: $(CTAGSDIR) + cd $(LIBDIR) + curl --insecure -L -R -O $(CURLCTAGSSRC) +# cd ctags + tar zxf $(CURLCTAGSDST) -C ctags + cd ..\sys\windows\vs\fetchctags + @echo ctags.exe has been fetched into $(LIBDIR)\ctags + +$(CTAGSDIR): $(LIBDIR) + @if not exist $(CTAGSDIR)\*.* echo creating directory $(CTAGSDIR:\=/) + @if not exist $(CTAGSDIR)\*.* mkdir $(CTAGSDIR) + +$(LIBDIR): + @if not exist $(LIBDIR)\*.* echo creating directory $(LIBDIR:\=/) + @if not exist $(LIBDIR)\*.* mkdir $(LIBDIR) + +rebuild: + @if exist $(CTAGSDIR)\ctags.exe echo nothing to do for $(CTAGSDIR)\ctags.exe + +clean: + if exist $(CURLCTAGSDST) del $(CURLCTAGSDST) + diff --git a/sys/windows/vs/fetchctags/fetchctags.vcxproj b/sys/windows/vs/fetchctags/fetchctags.vcxproj new file mode 100644 index 000000000..58df9ec83 --- /dev/null +++ b/sys/windows/vs/fetchctags/fetchctags.vcxproj @@ -0,0 +1,71 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + 17.0 + {AAE63AD3-8185-4E19-B6A3-13F4CB891AAD} + Win32Proj + 10.0 + + + + Makefile + true + + + Makefile + false + + + Makefile + true + + + Makefile + false + + + + + + + + + + + + echo ..\lib\ctags is already present + pushd $(vsDir)fetchctags %26%26 nmake -F fetchctags.nmake clean %26%26 popd + echo rebuilding $(vsDir)fetchctags + _DEBUG;$(NMakePreprocessorDefinitions) + + + pushd $(vsDir)fetchctags %26%26 nmake -F fetchctags.nmake %26%26 popd + pushd $(vsDir)fetchctags %26%26 nmake -F fetchctags.nmake clean %26%26 popd + pushd $(vsDir)fetchprereq %26%26 nmake -F fetchctags.nmake rebuild %26%26 popd + _DEBUG;$(NMakePreprocessorDefinitions) + + + + + + diff --git a/sys/windows/vs/sfctool.sln b/sys/windows/vs/sfctool.sln new file mode 100644 index 000000000..c997bd45f --- /dev/null +++ b/sys/windows/vs/sfctool.sln @@ -0,0 +1,58 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.13.35913.81 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sfctool", "sfctool\sfctool.vcxproj", "{3BFA3C14-6DA2-4750-B1C6-028B9BCE825E}" + ProjectSection(ProjectDependencies) = postProject + {628C594A-7565-4366-9FCA-41DB67C6B615} = {628C594A-7565-4366-9FCA-41DB67C6B615} + {AAE63AD3-8185-4E19-B6A3-13F4CB891AAD} = {AAE63AD3-8185-4E19-B6A3-13F4CB891AAD} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sftags", "sftags\sftags.vcxproj", "{628C594A-7565-4366-9FCA-41DB67C6B615}" + ProjectSection(ProjectDependencies) = postProject + {AAE63AD3-8185-4E19-B6A3-13F4CB891AAD} = {AAE63AD3-8185-4E19-B6A3-13F4CB891AAD} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fetchctags", "fetchctags\fetchctags.vcxproj", "{AAE63AD3-8185-4E19-B6A3-13F4CB891AAD}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {3BFA3C14-6DA2-4750-B1C6-028B9BCE825E}.Debug|x64.ActiveCfg = Debug|x64 + {3BFA3C14-6DA2-4750-B1C6-028B9BCE825E}.Debug|x64.Build.0 = Debug|x64 + {3BFA3C14-6DA2-4750-B1C6-028B9BCE825E}.Debug|x86.ActiveCfg = Debug|Win32 + {3BFA3C14-6DA2-4750-B1C6-028B9BCE825E}.Debug|x86.Build.0 = Debug|Win32 + {3BFA3C14-6DA2-4750-B1C6-028B9BCE825E}.Release|x64.ActiveCfg = Release|x64 + {3BFA3C14-6DA2-4750-B1C6-028B9BCE825E}.Release|x64.Build.0 = Release|x64 + {3BFA3C14-6DA2-4750-B1C6-028B9BCE825E}.Release|x86.ActiveCfg = Release|Win32 + {3BFA3C14-6DA2-4750-B1C6-028B9BCE825E}.Release|x86.Build.0 = Release|Win32 + {628C594A-7565-4366-9FCA-41DB67C6B615}.Debug|x64.ActiveCfg = Debug|x64 + {628C594A-7565-4366-9FCA-41DB67C6B615}.Debug|x64.Build.0 = Debug|x64 + {628C594A-7565-4366-9FCA-41DB67C6B615}.Debug|x86.ActiveCfg = Debug|Win32 + {628C594A-7565-4366-9FCA-41DB67C6B615}.Debug|x86.Build.0 = Debug|Win32 + {628C594A-7565-4366-9FCA-41DB67C6B615}.Release|x64.ActiveCfg = Release|x64 + {628C594A-7565-4366-9FCA-41DB67C6B615}.Release|x64.Build.0 = Release|x64 + {628C594A-7565-4366-9FCA-41DB67C6B615}.Release|x86.ActiveCfg = Release|Win32 + {628C594A-7565-4366-9FCA-41DB67C6B615}.Release|x86.Build.0 = Release|Win32 + {AAE63AD3-8185-4E19-B6A3-13F4CB891AAD}.Debug|x64.ActiveCfg = Debug|x64 + {AAE63AD3-8185-4E19-B6A3-13F4CB891AAD}.Debug|x64.Build.0 = Debug|x64 + {AAE63AD3-8185-4E19-B6A3-13F4CB891AAD}.Debug|x86.ActiveCfg = Debug|Win32 + {AAE63AD3-8185-4E19-B6A3-13F4CB891AAD}.Debug|x86.Build.0 = Debug|Win32 + {AAE63AD3-8185-4E19-B6A3-13F4CB891AAD}.Release|x64.ActiveCfg = Release|x64 + {AAE63AD3-8185-4E19-B6A3-13F4CB891AAD}.Release|x64.Build.0 = Release|x64 + {AAE63AD3-8185-4E19-B6A3-13F4CB891AAD}.Release|x86.ActiveCfg = Release|Win32 + {AAE63AD3-8185-4E19-B6A3-13F4CB891AAD}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {1000CD98-D3C0-493F-9EA7-E2D81FA96432} + EndGlobalSection +EndGlobal diff --git a/sys/windows/vs/sfctool/sfctool.vcxproj b/sys/windows/vs/sfctool/sfctool.vcxproj new file mode 100644 index 000000000..f86aa0b8b --- /dev/null +++ b/sys/windows/vs/sfctool/sfctool.vcxproj @@ -0,0 +1,193 @@ + + + + + + + + + + + $(BinDir) + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 17.0 + Win32Proj + {3bfa3c14-6da2-4750-b1c6-028b9bce825e} + sfctool + 10.0 + + + + Application + true + v143 + Unicode + + + Application + false + v143 + true + Unicode + + + Application + true + v143 + Unicode + + + Application + false + v143 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + $(WinWin32Dir);$(IncDir);$(SysWindDir);$(SysShareDir);$(WinShareDir);$(LuaDir);$(UtilDir);%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_CONSOLE;WIN32CON;NO_TILE_C;DLB;SAFEPROCS;SND_LIB_WINDSOUND;USER_SOUNDS;_LIB;HAS_STDINT_H;SFCTOOL;NOPANICTRACE;NOCRASHREPORT;NO_CHRONICLE;%(PreprocessorDefinitions) + Level3 + true + true + + + Console + true + $(ToolsDir);%(AdditionalLibraryDirectories) + hacklib.lib;%(AdditionalDependencies) + + + + + $(WinWin32Dir);$(IncDir);$(SysWindDir);$(SysShareDir);$(WinShareDir);$(LuaDir);$(UtilDir);%(AdditionalIncludeDirectories) + WIN32;_NDEBUG;_CONSOLE;WIN32CON;NO_TILE_C;DLB;SAFEPROCS;SND_LIB_WINDSOUND;USER_SOUNDS;_LIB;HAS_STDINT_H;SFCTOOL;NOPANICTRACE;NOCRASHREPORT;NO_CHRONICLE;%(PreprocessorDefinitions) + Level3 + true + true + true + true + + + Console + true + true + true + $(ToolsDir);%(AdditionalLibraryDirectories) + hacklib.lib;%(AdditionalDependencies) + + + + + $(WinWin32Dir);$(IncDir);$(SysWindDir);$(SysShareDir);$(WinShareDir);$(LuaDir);$(UtilDir);%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_CONSOLE;WIN32CON;NO_TILE_C;DLB;SAFEPROCS;SND_LIB_WINDSOUND;USER_SOUNDS;_LIB;HAS_STDINT_H;SFCTOOL;NOPANICTRACE;NOCRASHREPORT;NO_CHRONICLE;%(PreprocessorDefinitions) + Level3 + true + true + + + Console + true + $(ToolsDir);%(AdditionalLibraryDirectories) + hacklib.lib;userenv.lib;advapi32.lib;%(AdditionalDependencies) + + + + + $(WinWin32Dir);$(IncDir);$(SysWindDir);$(SysShareDir);$(WinShareDir);$(LuaDir);$(UtilDir);%(AdditionalIncludeDirectories) + WIN32;_NDEBUG;_CONSOLE;WIN32CON;NO_TILE_C;DLB;SAFEPROCS;SND_LIB_WINDSOUND;USER_SOUNDS;_LIB;HAS_STDINT_H;SFCTOOL;NOPANICTRACE;NOCRASHREPORT;NO_CHRONICLE;%(PreprocessorDefinitions) + Level3 + true + true + true + true + + + Console + true + true + true + $(ToolsDir);%(AdditionalLibraryDirectories) + hacklib.lib;userenv.lib;advapi32.lib;$(CoreLibraryDependencies);%(AdditionalDependencies) + + + + + + diff --git a/sys/windows/vs/sftags/aftersftags.proj b/sys/windows/vs/sftags/aftersftags.proj new file mode 100644 index 000000000..a79669104 --- /dev/null +++ b/sys/windows/vs/sftags/aftersftags.proj @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sys/windows/vs/sftags/sftags.vcxproj b/sys/windows/vs/sftags/sftags.vcxproj new file mode 100644 index 000000000..4131dcd5c --- /dev/null +++ b/sys/windows/vs/sftags/sftags.vcxproj @@ -0,0 +1,156 @@ + + + + + + + + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + 17.0 + Win32Proj + {628c594a-7565-4366-9fca-41db67c6b615} + sftags + 10.0 + + + + Application + true + v143 + Unicode + + + Application + false + v143 + true + Unicode + + + Application + true + v143 + Unicode + + + Application + false + v143 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + $(WinWin32Dir);$(IncDir);$(SysWindDir);$(SysShareDir);$(WinShareDir);$(LuaDir);$(UtilDir);%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_CONSOLE;WIN32CON;NO_TILE_C;DLB;SAFEPROCS;SND_LIB_WINDSOUND;USER_SOUNDS;_LIB;HAS_STDINT_H;SFCTOOL;NOPANICTRACE;NOCRASHREPORT;NO_CHRONICLE;%(PreprocessorDefinitions) + Level3 + true + true + + + Console + true + + + + + $(WinWin32Dir);$(IncDir);$(SysWindDir);$(SysShareDir);$(WinShareDir);$(LuaDir);$(UtilDir);%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_CONSOLE;WIN32CON;NO_TILE_C;DLB;SAFEPROCS;SND_LIB_WINDSOUND;USER_SOUNDS;_LIB;HAS_STDINT_H;SFCTOOL;NOPANICTRACE;NOCRASHREPORT;NO_CHRONICLE;%(PreprocessorDefinitions) + Level3 + true + true + true + true + + + Console + true + true + true + + + + + $(WinWin32Dir);$(IncDir);$(SysWindDir);$(SysShareDir);$(WinShareDir);$(LuaDir);$(UtilDir);%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_CONSOLE;WIN32CON;NO_TILE_C;DLB;SAFEPROCS;SND_LIB_WINDSOUND;USER_SOUNDS;_LIB;HAS_STDINT_H;SFCTOOL;NOPANICTRACE;NOCRASHREPORT;NO_CHRONICLE;%(PreprocessorDefinitions) + Level3 + true + true + + + Console + true + + + + + $(WinWin32Dir);$(IncDir);$(SysWindDir);$(SysShareDir);$(WinShareDir);$(LuaDir);$(UtilDir);%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_CONSOLE;WIN32CON;NO_TILE_C;DLB;SAFEPROCS;SND_LIB_WINDSOUND;USER_SOUNDS;_LIB;HAS_STDINT_H;SFCTOOL;NOPANICTRACE;NOCRASHREPORT;NO_CHRONICLE;%(PreprocessorDefinitions) + Level3 + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + + + + + + + + + + + diff --git a/sys/windows/windsys.c b/sys/windows/windsys.c index d7178cffa..6be9b6407 100644 --- a/sys/windows/windsys.c +++ b/sys/windows/windsys.c @@ -44,6 +44,10 @@ static char portable_device_path[MAX_PATH]; +static boolean path_buffer_set = FALSE; +static char path_buffer[MAX_PATH]; + +#ifndef SFCTOOL /* runtime cursor display control switch */ boolean win32_cursorblink; @@ -53,6 +57,9 @@ WIN32_FIND_DATA ffd; extern int GUILaunched; extern boolean getreturn_enabled; int redirect_stdout; +static char *get_executable_path(void); + + #ifdef WIN32CON typedef HWND(WINAPI *GETCONSOLEWINDOW)(void); @@ -780,7 +787,9 @@ nt_assert_failed(const char *expression, const char *filepath, int line) impossible("nhassert(%s) failed in file '%s' at line %d", expression, filename, line); } +#endif /* SFCTOOL */ +/* used by util/sfctool.c as well as files.c */ boolean get_user_home_folder(char *homebuf, size_t sz) { @@ -794,13 +803,12 @@ get_user_home_folder(char *homebuf, size_t sz) result = GetUserProfileDirectoryA(hToken, szHomeDirBuf, &BufSize); // Close handle opened via OpenProcessToken CloseHandle(hToken); + if (result != 0) { + Snprintf(homebuf, sz, "%s", szHomeDirBuf); + } return (result != 0); } -static char *get_executable_path(void); - -static boolean path_buffer_set = FALSE; -static char path_buffer[MAX_PATH]; char * get_executable_path(void) @@ -1019,6 +1027,7 @@ set_default_prefix_locations(const char *programPath UNUSED) strcpy(executable_path, get_executable_path()); append_slash(executable_path); +#ifndef SFCTOOL if (test_portable_config(executable_path, portable_device_path, sizeof portable_device_path)) { gf.fqn_prefix[SYSCONFPREFIX] = executable_path; @@ -1032,6 +1041,7 @@ set_default_prefix_locations(const char *programPath UNUSED) gf.fqn_prefix[TROUBLEPREFIX] = portable_device_path; gf.fqn_prefix[DATAPREFIX] = executable_path; } else { +#endif /* SFCTOOL */ if (!build_known_folder_path(&FOLDERID_Profile, profile_path, sizeof(profile_path), FALSE)) strcpy(profile_path, executable_path); @@ -1061,7 +1071,9 @@ set_default_prefix_locations(const char *programPath UNUSED) gf.fqn_prefix[LOCKPREFIX] = versioned_global_data_path; gf.fqn_prefix[TROUBLEPREFIX] = versioned_profile_path; gf.fqn_prefix[DATAPREFIX] = executable_path; +#ifndef SFCTOOL } +#endif /* SFCTOOL */ } /* @@ -1138,6 +1150,7 @@ get_portable_device(void) return (const char *) portable_device_path; } +#ifndef SFCTOOL /* Windows helpers for CRASHREPORT etc */ #ifdef CRASHREPORT struct CRctxt { @@ -1429,6 +1442,7 @@ win32_cr_shellexecute(const char *url){ return rv; } #endif /* CRASHREPORT */ +#endif /* SFCTOOL */ #endif /* WIN32 */ diff --git a/util/.gitignore b/util/.gitignore index 11fa8a1f0..a16d5c640 100644 --- a/util/.gitignore +++ b/util/.gitignore @@ -31,4 +31,7 @@ heaputil.c tilemappings.lst clang_rt.asan*.dll *.sln - +sf.tags +sfdata.c +sfctool +sftags diff --git a/util/sfctool.c b/util/sfctool.c new file mode 100644 index 000000000..cc3f9e464 --- /dev/null +++ b/util/sfctool.c @@ -0,0 +1,1323 @@ +/* NetHack 3.7 sfctool.c */ +/* Copyright (c) Michael Allison, 2025. */ +/* NetHack may be freely redistributed. See license for details. */ + +/* + * Utility for reading a binary save file in the native historical + * format of the accompanying NetHack executable, and writing it out + * in an export format, possibly destined for a different platform, + * architecture, or data model. + * + * The resulting export file will only be useful for transport + * between different platforms and architectures that share the exact + * same version of NetHack with the same features. That is, the same + * fields must be present in the NetHack data structures, in the same + * sequence. The fields do not have to be the same size or use the same + * data model. + * + */ + +#if defined(WIN32) && !defined(__GNUC__) +#include "win32api.h" +#endif + +#include "hack.h" + +#include +#include +#include +#ifdef UNIX +#include +#define O_BINARY 0 +#endif +#include "integer.h" +#include "sfprocs.h" + +#ifdef WIN32 +#include +#endif + +#ifndef RDTMODE +#define RDTMODE "r" +#endif +#ifndef WRTMODE +#if (defined(MSDOS) || defined(WIN32)) +#define WRTMODE "w+b" +#else +#define WRTMODE "w+" +#endif +#endif +#ifndef RDBMODE +#if (defined(MICRO) || defined(WIN32)) +#define RDBMODE "rb" +#else +#define RDBMODE "r" +#endif +#endif +#ifndef WRBMODE +#if (defined(MICRO) || defined(WIN32)) +#define WRBMODE "w+b" +#else +#define WRBMODE "w+" +#endif +#endif + +#ifdef PANICTRACE +#error PANICTRACE is defined +#endif +#ifdef CRASHREPORT +#error CRASHREPORT is defined +#endif + +/* functions in this file */ +static int process_savefile(const char *, enum saveformats, char *, enum saveformats, boolean); +static void my_sf_init(void); +static NHFILE *open_srcfile(const char *, enum saveformats); +static NHFILE *create_dstfile(char *, enum saveformats); +static const char *style_to_text(enum saveformats style); +static void read_sysconf(void); +static int length_without_val(const char *user_string, int len); + +void zero_nhfile(NHFILE *); +NHFILE *new_nhfile(void); +void free_nhfile(NHFILE *); +void my_close_nhfile(NHFILE *); +int delete_savefile(void); +int nhclose(int fd); +int util_strncmpi(const char *s1, const char *s2, size_t sz); + +#ifdef UNIX +#define nethack_exit exit +void nh_terminate(int) NORETURN; /* bwrite() calls this */ +static void chdirx(const char *); +#else +extern void nethack_exit(int) NORETURN; +#ifdef WIN32 +boolean get_user_home_folder(char *homebuf, size_t sz); +int GUILaunched; +#endif /* WIN32 */ +#endif +#define Fprintf (void) fprintf + +/* Global data */ + +struct link_compat1 { + volatile int done_hup; +}; + +/* worm segment structure */ +struct wseg { + struct wseg *nseg; + coordxy wx, wy; /* the segment's position */ +}; + +enum { UNCONVERTED = 0, CONVERTED }; +char *unconverted_filename = 0; +char *converted_filename = 0; + +/* from sfstruct.c */ +extern struct restore_info restoreinfo; +/* from sfbase.c */ +extern struct sf_structlevel_procs sfoprocs[NUM_SAVEFORMATS], sfiprocs[NUM_SAVEFORMATS]; +extern struct sf_structlevel_procs zerosfoprocs, zerosfiprocs; +extern struct sf_fieldlevel_procs sfoflprocs[NUM_SAVEFORMATS], sfiflprocs[NUM_SAVEFORMATS]; +extern struct sf_structlevel_procs zerosfodlprocs, zerosfidlprocs; +extern boolean close_check(int); +extern void bclose(int); +extern void config_error_init(boolean, const char *, boolean); /* files.c */ +extern boolean get_user_home_folder(char *, size_t); +extern void make_version(void); + +char plname[PL_NSIZ_PLUS]; +struct version_info vers_info; +int renidx = -1; + +const char *const rensuffixes[] = { + "IL32LLP64", /* (3) Windows x64 savefile on x86 */ + "I32LP64", /* (4) Unix 64 savefile on x86 */ + "ILP32LL64", /* (5) x86 savefile on Unix 64 */ + "ILP32LL64", /* (6) x86 savefile on Windows x64 */ + "I32LP64", /* (7) Unix 64 savefile on Windows x64 */ + "IL32LLP64", /* (8) Windows x64 savefile on Unix 64 */ + "OTHER", /* (9) */ +}; + +#ifdef WIN32 +extern boolean get_user_home_folder(char *homebuf, size_t sz); /* files.c */ +extern void set_default_prefix_locations(const char *programPath); +#endif + +enum saveformats convertstyle = exportascii; + +boolean chosen_unconvert = FALSE, explicit_option = FALSE; +const char *thisdatamodel; +static char srclogfilenm[BUFSZ], dstlogfilenm[BUFSZ]; + +/********* + * main * + *********/ + +int +main(int argc UNUSED, char *argv[]) +{ + int arg; + char folderbuf[5000]; + const char *suffix = (convertstyle == exportascii) ? ".exportascii" : ""; + boolean add_folder = TRUE; +#ifdef WIN32 + size_t sz; +#endif + + if (argc < 3) + exit(EXIT_FAILURE); + + runtime_info_init(); /* mdlib.c */ +#ifdef UNIX + folderbuf[0] = '.'; + folderbuf[1] = '/'; + folderbuf[2] = '\0'; +#ifdef CHDIR + chdirx(HACKDIR); +#endif +#endif +#ifdef UNIX + Strcpy(folderbuf, "save/"); +#endif +#ifdef WIN32 + if (!get_user_home_folder(folderbuf, sizeof folderbuf)) + exit(EXIT_FAILURE); + sz = strlen(folderbuf); + (void) snprintf(eos(folderbuf), sizeof folderbuf - sz, + "\\AppData\\Local\\NetHack\\3.7\\"); + //initoptions_init(); // This allows OPTIONS in syscf on Windows. + set_default_prefix_locations(argv[0]); +#endif + + read_sysconf(); + for (arg = 1; arg < argc; ++arg) { + if (arg == 1 && !strcmp(argv[arg], "-u")) { + explicit_option = TRUE; + chosen_unconvert = TRUE; + continue; + } + if (arg == 1 && !strcmp(argv[arg], "-c")) { + if (explicit_option && chosen_unconvert) { + fprintf(stderr, "\nsfctool error - conflicting options.\n"); + exit(EXIT_FAILURE); /* both -u and -c not allowed */ + } + explicit_option = TRUE; + chosen_unconvert = FALSE; + continue; + } + if (arg == 2) { + size_t ln = strlen(argv[arg]); + boolean addseparator = FALSE; + + if (!contains_directory(argv[arg])) { + char finalchar = *(eos(folderbuf) - 1); + + if (!(finalchar == '\\' || finalchar == '/')) { + ln += 1; + addseparator = TRUE; + } + } else { + add_folder = FALSE; + } + if (explicit_option) { + if (add_folder) + ln += strlen(folderbuf); + unconverted_filename = (char *) alloc((int) ln + 1); + Snprintf(unconverted_filename, ln + 1, "%s%s%s", + add_folder ? folderbuf : "", + addseparator ? "/" : "", argv[arg]); + ln += strlen(suffix); + converted_filename = (char *) alloc((int) ln + 1); + Snprintf(converted_filename, ln + 1, "%s%s", + unconverted_filename, suffix); + } else { + fprintf(stderr, "\nsfctool error - missing -c or -u before " + "save filename.\n"); + exit(EXIT_FAILURE); /* need both filenames */ + } + } + } + if (!converted_filename || !unconverted_filename) { + fprintf(stderr, "\nsfctool error - missing %sconverted file name.\n", + !converted_filename ? "" : "un"); + exit(EXIT_FAILURE); /* need both filenames */ + } + thisdatamodel = datamodel(); + my_sf_init(); + if (chosen_unconvert) { + process_savefile(converted_filename, convertstyle, + unconverted_filename, historical, chosen_unconvert); + } else { + process_savefile(unconverted_filename, historical, converted_filename, + convertstyle, chosen_unconvert); + } +} + +/* ======================================================================== */ +/* Process the src savefile and create the dst file */ +/* Return 1 for success, 0 for failure */ +/* ======================================================================== */ + +static int +process_savefile(const char *srcfnam, enum saveformats srcstyle, + char *dstfnam, enum saveformats cvtstyle, boolean unconvert) +{ + NHFILE *nhfp[2]; /* one for UNCONVERTED, one for CONVERTED */ + int srcidx = unconvert ? CONVERTED : UNCONVERTED, + dstidx = unconvert ? UNCONVERTED : CONVERTED, + sfstatus = 0, i; + char indicator, file_csc_count; + extern struct version_info vers_info; + extern uchar cscbuf[]; + /* nh_uncompress(fq_save); */ + + if ((nhfp[srcidx] = open_srcfile(srcfnam, srcstyle)) == 0) + return 0; + sfstatus = validate(nhfp[srcidx], srcfnam, FALSE); + if (sfstatus > SF_UPTODATE + && ((sfstatus <= SF_CRITICAL_BYTE_COUNT_MISMATCH) || !unconvert)) { + fprintf(stderr, + "This savefile is not compatible with %sutility.\n%s\n", + !unconvert ? "the datamodel of this particular " : "this ", + srcfnam); + return 0; + } + if (sfstatus >= SF_DM_IL32LLP64_ON_ILP32LL64) { + renidx = sfstatus - SF_DM_IL32LLP64_ON_ILP32LL64; + } else if (sfstatus == SF_UPTODATE) { + renidx = -2; + } + if ((nhfp[dstidx] = create_dstfile(dstfnam, cvtstyle)) == 0) { + close_nhfile(nhfp[dstidx]); + nh_compress(unconverted_filename); + return 0; + } + if (unconvert) { + nhfp[srcidx]->nhfpconvert = nhfp[UNCONVERTED]; + } else { + /* converting */ + nhfp[srcidx]->nhfpconvert = nhfp[CONVERTED]; + } + if (unconvert) + fprintf(stdout, "\n\nunconverting %s to %s %s\n", + style_to_text(srcstyle), style_to_text(cvtstyle), + thisdatamodel); + else + fprintf(stdout, "\n\nconverting %s %s to %s\n", + style_to_text(srcstyle), thisdatamodel, style_to_text(cvtstyle)); + + rewind_nhfile(nhfp[srcidx]); +#ifdef SAVEFILE_DEBUGGING + nhfp[srcidx]->fplog = fopen(srclogfilenm, "w"); +#endif + if (unconvert) { + nhfp[srcidx]->mode |= UNCONVERTING; + } else { + /* converting */ + nhfp[srcidx]->mode |= CONVERTING; + } + nhfp[srcidx]->rcount = 0; + Sfi_char(nhfp[srcidx], &indicator, "indicate-format", 1); + Sfi_char(nhfp[srcidx], &file_csc_count, "count-critical_sizes", 1); + for (i = 0; i < (int) file_csc_count; ++i) { + Sfi_uchar(nhfp[srcidx], &cscbuf[i], "critical_sizes"); + } + rewind_nhfile(nhfp[dstidx]); +#ifdef SAVEFILE_DEBUGGING + nhfp[dstidx]->fplog = fopen(dstlogfilenm, "w"); +#endif + /* + * store_critical_bytes() will take care of inserting the + * indicate-format, count-critical_sizes, and critical_sizes for + * this platform/data-model destination, instead of copying those + * values from the savefile that was converted. + */ + store_critical_bytes(nhfp[dstidx]); + + Sfi_version_info(nhfp[srcidx], &vers_info, "version_info"); + svm.moves = 1L; /* match u_init.c */ + + /******************** + * player name info * + ********************/ + + get_plname_from_file(nhfp[srcidx], plname, TRUE); + + { + /******************** + * lev 0 * + ********************/ + xint8 lev = 0; + + getlev(nhfp[srcidx], lev, FALSE); + } + + + { + /******************** + * gamestate * + ********************/ +/* unsigned int stuckid, steedid; */ + (void) restgamestate(nhfp[srcidx]); + } + + { + /******************** + * Do all levels * + ********************/ + xint8 ltmp; + + restoreinfo.mread_flags = 1; /* return despite error */ + while (1) { + ltmp = -1; + Sfi_xint8(nhfp[srcidx], <mp, "gamestate-level_number"); + if (nhfp[srcidx]->eof || ltmp == -1) + break; + + getlev(nhfp[srcidx], 0, ltmp); + } + restoreinfo.mread_flags = 0; + } + nhfp[srcidx]->mode &= ~(CONVERTING | UNCONVERTING); + nhfp[srcidx]->nhfpconvert = (NHFILE *) 0; + close_nhfile(nhfp[srcidx]); + close_nhfile(nhfp[dstidx]); + nh_compress(dstfnam); + nh_compress(srcfnam); + return 1; +} + +/* open srcfile for reading */ +static NHFILE * +open_srcfile(const char *fnam, enum saveformats mystyle) +{ + int fd; + const char *fq_name; + NHFILE *nhfp = (NHFILE *) 0; + + nhfp = new_nhfile(); + if (nhfp) { + nhfp->mode = READING; + nhfp->structlevel = (mystyle == historical); + nhfp->fieldlevel = (mystyle > historical); + nhfp->ftype = NHF_SAVEFILE; + nhfp->fnidx = mystyle; + nhfp->fd = -1; + nhfp->addinfo = + (nhfp->fieldlevel && (mystyle = exportascii)) + ? TRUE + : FALSE; + (void) snprintf(srclogfilenm, sizeof srclogfilenm, "srcfile.%s.log", + (mystyle == historical) ? "historical" : "exportascii"); + } + + fq_name = fqname(fnam, SAVEPREFIX, 0); + nh_uncompress(fq_name); + if (nhfp && nhfp->structlevel) { + fd = open(fq_name, O_RDONLY | O_BINARY, 0); + if (fd < 0) { + zero_nhfile(nhfp); + free_nhfile(nhfp); + fprintf(stderr, + "\nsfctool error - unable to open historical-style " + "source file %s.\n", + fnam); + nhfp = (NHFILE *) 0; + nh_compress(fq_name); + } else { + nhfp->fd = fd; +#if defined(MSDOS) + setmode(nhfp->fd, O_BINARY); +#endif + } + } + if (nhfp && nhfp->fieldlevel) { + /* char savenamebuf[BUFSZ]; */ + + nhfp->fpdef = fopen(fnam, RDBMODE); + if (!nhfp->fpdef) { + zero_nhfile(nhfp); + free_nhfile(nhfp); + fprintf(stderr, + "\nsfctool error - unable to open fieldlevel-style " + "source file %s.\n", + fnam); + nhfp = (NHFILE *) 0; + nh_compress(fq_name); + } + } + return nhfp; +} + +/* create dst file, overwriting one if it already exists */ +static NHFILE * +create_dstfile(char *fnam, enum saveformats mystyle) +{ + int fd, ret; + unsigned ln = 0; + FILE *cf; + NHFILE *nhfp = (NHFILE *) 0; + const char *fq_name; + char dstfnam[2048]; + char *dsttmp; + boolean dst_file_exists = FALSE, ren_file_exists = FALSE; + + nhUse(ret); + Snprintf(dstfnam, sizeof dstfnam, "%s", fnam); + if ((cf = fopen(dstfnam, RDBMODE)) != (FILE *) 0) { + dst_file_exists = TRUE; + (void) fclose(cf); + } + + if (dst_file_exists) { + if (chosen_unconvert) { + ln = strlen(fnam); + if (renidx >= 0) { + ln += strlen(rensuffixes[renidx]) + 1; /* +1 for '.' */ + } else if (renidx == -2) { + ln += strlen(thisdatamodel) + 1; /* +1 for '.' */ + } else { + ln += strlen(thisdatamodel) + 1 + + 4; /* +1 for '.'; +4 for "not_" */ + } + dsttmp = (char *) alloc(ln + 1); + Strcpy(dsttmp, fnam); + Strcat(dsttmp, "."); + if (renidx >= 0) { + Strcat(dsttmp, rensuffixes[renidx]); + } else if (renidx == -2) { + Strcat(dsttmp, thisdatamodel); + } else { + Strcat(dsttmp, "not_"); + Strcat(dsttmp, thisdatamodel); + } + if ((cf = fopen(dsttmp, RDBMODE)) != (FILE *) 0) { + ren_file_exists = TRUE; + (void) fclose(cf); + } + if (ren_file_exists) { + (void) unlink(dsttmp); + } + ret = rename(fnam, dsttmp); + free((genericptr_t) dsttmp), dsttmp = 0; + } else { + if ((cf = fopen(dstfnam, RDBMODE)) != (FILE *) 0) { + ren_file_exists = TRUE; + (void) fclose(cf); + } + if (ren_file_exists) { + (void) unlink(dstfnam); + } + } + } + + nhfp = new_nhfile(); + if (nhfp) { + nhfp->mode = WRITING; + nhfp->ftype = NHF_SAVEFILE; + nhfp->structlevel = (mystyle == historical); + nhfp->fieldlevel = (mystyle > historical); + nhfp->fnidx = mystyle; + nhfp->fd = -1; + (void) snprintf(dstlogfilenm, sizeof dstlogfilenm, "dstfile.%s.log", + (mystyle == historical) ? "historical" : "exportascii"); + } + + if (nhfp && nhfp->structlevel) { + fq_name = fqname(dstfnam, SAVEPREFIX, 0); +#if defined(MICRO) || defined(WIN32) + fd = open(dstfnam, O_WRONLY | O_BINARY | O_CREAT | O_TRUNC, FCMASK); +#else + fd = creat(dstfnam, FCMASK); +#endif + if (fd < 0) { + zero_nhfile(nhfp); + free_nhfile(nhfp); + fprintf( + stderr, + "Unable to create historical-style destination file %s.\n", + fnam); + nhfp = (NHFILE *) 0; + } else { + nhfp->fd = fd; +#if defined(MSDOS) + setmode(nhfp->fd, O_BINARY); +#endif + } + } else if (nhfp && nhfp->fieldlevel) { + fq_name = fqname(dstfnam, SAVEPREFIX, 0); + nhfp->fpdef = fopen(fq_name, WRBMODE); + if (!nhfp->fpdef) { + zero_nhfile(nhfp); + free_nhfile(nhfp); + fprintf( + stderr, + "Unable to create fieldlevel-style destination file %s.\n", + fnam); + nhfp = (NHFILE *) 0; + } + } + return nhfp; +} + +static const char * +style_to_text(enum saveformats style) +{ + const char *txt; + + switch (style) { + case historical: + txt = "historical"; + break; + case exportascii: + txt = "exportascii"; + break; + case invalid: + default: + txt = "invalid"; + break; + } + return txt; +} + +void +my_sf_init(void) +{ + decl_globals_init(); + sfoprocs[invalid] = zerosfoprocs; + sfiprocs[invalid] = zerosfiprocs; + sfoprocs[historical] = historical_sfo_procs; + sfiprocs[historical] = historical_sfi_procs; + sfoflprocs[exportascii] = exportascii_sfo_procs; + sfiflprocs[exportascii] = exportascii_sfi_procs; +} + +/* delete savefile */ +int +delete_savefile(void) +{ + return 0; /* for restore_saved_game() (ex-xxxmain.c) test */ +} + +static void +read_sysconf(void) +{ +#ifdef SYSCF +/* someday there may be other SYSCF alternatives besides text file */ +#ifdef SYSCF_FILE + /* If SYSCF_FILE is specified, it _must_ exist... */ + assure_syscf_file(); + config_error_init(TRUE, SYSCF_FILE, FALSE); + if (!read_config_file(SYSCF_FILE, set_in_sysconf)) { + if (config_error_done() && !iflags.initoptions_noterminate) + nh_terminate(EXIT_FAILURE); + } + config_error_done(); + /* + * TODO [maybe]: parse the sysopt entries which are space-separated + * lists of usernames into arrays with one name per element. + */ +#endif +#endif /* SYSCF */ +} + + +DISABLE_WARNING_FORMAT_NONLITERAL + +/* provided for linkage only */ +void +error(const char *s, ...) +{ + va_list the_args; + + va_start(the_args, s); + printf(s, the_args); + va_end(the_args); + exit(EXIT_FAILURE); +} + +void +pline(const char *s, ...) +{ + va_list the_args; + + va_start(the_args, s); + printf(s, the_args); + va_end(the_args); +} + +void +impossible(const char *s, ...) +{ + va_list the_args; + + va_start(the_args, s); + printf(s, the_args); + va_end(the_args); + exit(EXIT_FAILURE); +} + +RESTORE_WARNING_FORMAT_NONLITERAL + +/* TIME_type: type of the argument to time(); we actually use &(time_t) */ +#if defined(BSD) && !defined(POSIX_TYPES) +#define TIME_type long * +#else +#define TIME_type time_t * +#endif +/* LOCALTIME_type: type of the argument to localtime() */ +#if (defined(ULTRIX) && !(defined(ULTRIX_PROTO) || defined(NHSTDC))) \ + || (defined(BSD) && !defined(POSIX_TYPES)) +#define LOCALTIME_type long * +#else +#define LOCALTIME_type time_t * +#endif + +#if defined(AMIGA) && !defined(AZTEC_C) && !defined(__SASC_60) \ + && !defined(_DCC) && !defined(__GNUC__) +extern struct tm *localtime(time_t *); +#endif +static struct tm *getlt(void); + +time_t +getnow(void) +{ + time_t datetime = 0; + + (void) time((TIME_type) &datetime); + return datetime; +} + +static struct tm * +getlt(void) +{ + time_t date = getnow(); + + return localtime((LOCALTIME_type) &date); +} + +int +getyear(void) +{ + return (1900 + getlt()->tm_year); +} + +time_t +time_from_yyyymmddhhmmss(char *buf) +{ + int k; + time_t timeresult = (time_t) 0; + struct tm t, *lt; + char *d, *p, y[5], mo[3], md[3], h[3], mi[3], s[3]; + + if (buf && strlen(buf) == 14) { + d = buf; + p = y; /* year */ + for (k = 0; k < 4; ++k) + *p++ = *d++; + *p = '\0'; + p = mo; /* month */ + for (k = 0; k < 2; ++k) + *p++ = *d++; + *p = '\0'; + p = md; /* day */ + for (k = 0; k < 2; ++k) + *p++ = *d++; + *p = '\0'; + p = h; /* hour */ + for (k = 0; k < 2; ++k) + *p++ = *d++; + *p = '\0'; + p = mi; /* minutes */ + for (k = 0; k < 2; ++k) + *p++ = *d++; + *p = '\0'; + p = s; /* seconds */ + for (k = 0; k < 2; ++k) + *p++ = *d++; + *p = '\0'; + lt = getlt(); + if (lt) { + t = *lt; + t.tm_year = atoi(y) - 1900; + t.tm_mon = atoi(mo) - 1; + t.tm_mday = atoi(md); + t.tm_hour = atoi(h); + t.tm_min = atoi(mi); + t.tm_sec = atoi(s); + timeresult = mktime(&t); + } + return timeresult; + } + return (time_t) 0; +} + +char * +yyyymmddhhmmss(time_t date) +{ + long datenum; + static char datestr[15]; + struct tm *lt; + + if (date == 0) + lt = getlt(); + else +#if (defined(ULTRIX) && !(defined(ULTRIX_PROTO) || defined(NHSTDC))) \ + || defined(BSD) + lt = localtime((long *) (&date)); +#else + lt = localtime(&date); +#endif + /* just in case somebody's localtime supplies (year % 100) + rather than the expected (year - 1900) */ + if (lt->tm_year < 70) + datenum = (long) lt->tm_year + 2000L; + else + datenum = (long) lt->tm_year + 1900L; + Snprintf(datestr, sizeof datestr, "%04ld%02d%02d%02d%02d%02d", + datenum, lt->tm_mon + 1, + lt->tm_mday, lt->tm_hour, lt->tm_min, lt->tm_sec); + return datestr; +} + +DISABLE_WARNING_FORMAT_NONLITERAL + +void +raw_printf(const char *line, ...) +{ + va_list the_args; + + va_start(the_args, line); + fprintf(stdout, line, the_args); + va_end(the_args); +} + +RESTORE_WARNING_FORMAT_NONLITERAL + +#ifdef UNIX +/* normalize file name - we don't like .'s, /'s, spaces */ +void +regularize(char *s) +{ + register char *lp; + + while ((lp = strchr(s, '.')) != 0 || (lp = strchr(s, '/')) != 0 + || (lp = strchr(s, ' ')) != 0) + *lp = '_'; +#if defined(SYSV) && !defined(AIX_31) && !defined(SVR4) && !defined(LINUX) \ + && !defined(__APPLE__) +/* avoid problems with 14 character file name limit */ +#ifdef COMPRESS + /* leave room for .e from error and .Z from compress appended to + * save files */ + { +#ifdef COMPRESS_EXTENSION + int i = 12 - strlen(COMPRESS_EXTENSION); +#else + int i = 10; /* should never happen... */ +#endif + if (strlen(s) > i) + s[i] = '\0'; + } +#else + if (strlen(s) > 11) + /* leave room for .nn appended to level files */ + s[11] = '\0'; +#endif +#endif +} +#endif + +int +util_strncmpi(const char *s1, const char *s2, size_t sz) +{ + register char t1, t2; + + while (sz--) { + if (!*s2) + return (*s1 != 0); /* s1 >= s2 */ + else if (!*s1) + return -1; /* s1 < s2 */ + t1 = lowc(*s1++); + t2 = lowc(*s2++); + if (t1 != t2) + return (t1 > t2) ? 1 : -1; + } + return 0; /* s1 == s2 */ +} + +/* should be called with either EXIT_SUCCESS or EXIT_FAILURE */ +void +nh_terminate(int status) +{ + nethack_exit(status); +} + +#ifndef UNIX +void +nethack_exit(int code) +{ + exit(code); +} +#endif /* UNIX */ + +#ifdef UNIX +#ifdef CHDIR +static void +chdirx(const char *dir) +{ + if (dir) { +#ifdef SECURE + (void) setgid(getgid()); + (void) setuid(getuid()); /* Ron Wessels */ +#endif + } else { + /* non-default data files is a sign that scores may not be + * compatible, or perhaps that a binary not fitting this + * system's layout is being used. + */ +#ifdef VAR_PLAYGROUND + int len = strlen(VAR_PLAYGROUND); + + gf.fqn_prefix[SCOREPREFIX] = (char *) alloc(len + 2); + Strcpy(gf.fqn_prefix[SCOREPREFIX], VAR_PLAYGROUND); + if (gf.fqn_prefix[SCOREPREFIX][len - 1] != '/') { + gf.fqn_prefix[SCOREPREFIX][len] = '/'; + gf.fqn_prefix[SCOREPREFIX][len + 1] = '\0'; + } + +#endif + } + +#ifdef HACKDIR + if (dir == (const char *) 0) + dir = HACKDIR; +#endif + + if (dir && chdir(dir) < 0) { + perror(dir); + error("Cannot chdir to %s.", dir); + } +} +#endif /* CHDIR */ +#endif /* UNIX */ + +#ifdef WIN32 + +/* + * Strip out troublesome file system characters. + */ + +void nt_regularize(char* s) /* normalize file name */ +{ + unsigned char *lp; + + for (lp = (unsigned char *) s; *lp; lp++) + if (*lp == '?' || *lp == '"' || *lp == '\\' || *lp == '/' + || *lp == '>' || *lp == '<' || *lp == '*' || *lp == '|' + || *lp == ':' || (*lp > 127)) + *lp = '_'; +} +#endif /* WIN32 */ + +/* duplicated code from options.c */ +/* most environment variables will eventually be printed in an error + * message if they don't work, and most error message paths go through + * BUFSZ buffers, which could be overflowed by a maliciously long + * environment variable. If a variable can legitimately be long, or + * if it's put in a smaller buffer, the responsible code will have to + * bounds-check itself. + */ +char * +nh_getenv(const char *ev) +{ + char *getev = getenv(ev); + + if (getev && strlen(getev) <= (BUFSZ / 2)) + return getev; + else + return (char *) 0; +} + +void +done1(int sig_unused UNUSED) +{ +#ifndef NO_SIGNAL + (void) signal(SIGINT, SIG_IGN); +#endif + if (flags.ignintr) { +#ifndef NO_SIGNAL + (void) signal(SIGINT, (SIG_RET_TYPE) done1); +#endif + } +} + +/* + * I hate having to duplicate this code here, but it is much simpler to + * add these here than take steps to link with mkobj.c, do_name.c, priest.c, + * vault.c, shknam.c, minion.c, dog.c, etc. + */ + +/* allocate space for a monster's name; removes old name if there is one */ +void +new_mgivenname(struct monst *mon, + int lth) /* desired length (caller handles adding 1 + for terminator) */ +{ + if (lth) { + /* allocate mextra if necessary; otherwise get rid of old name */ + if (!mon->mextra) + mon->mextra = newmextra(); + else + free_mgivenname(mon); /* already has mextra, might also have name */ + MGIVENNAME(mon) = (char *) alloc((unsigned) lth); + } else { + /* zero length: the new name is empty; get rid of the old name */ + if (has_mgivenname(mon)) + free_mgivenname(mon); + } +} + +/* release a monster's name; retains mextra even if all fields are now null */ +void +free_mgivenname(struct monst *mon) +{ + if (has_mgivenname(mon)) { + free((genericptr_t) MGIVENNAME(mon)); + MGIVENNAME(mon) = (char *) 0; + } +} +void +newegd(struct monst *mtmp) +{ + if (!mtmp->mextra) + mtmp->mextra = newmextra(); + if (!EGD(mtmp)) { + EGD(mtmp) = (struct egd *) alloc(sizeof (struct egd)); + (void) memset((genericptr_t) EGD(mtmp), 0, sizeof (struct egd)); + } +} + +void +free_egd(struct monst *mtmp) +{ + if (mtmp->mextra && EGD(mtmp)) { + free((genericptr_t) EGD(mtmp)); + EGD(mtmp) = (struct egd *) 0; + } + mtmp->isgd = 0; +} +void +newepri(struct monst *mtmp) +{ + if (!mtmp->mextra) + mtmp->mextra = newmextra(); + if (!EPRI(mtmp)) { + EPRI(mtmp) = (struct epri *) alloc(sizeof(struct epri)); + (void) memset((genericptr_t) EPRI(mtmp), 0, sizeof(struct epri)); + } +} + +void +free_epri(struct monst *mtmp) +{ + if (mtmp->mextra && EPRI(mtmp)) { + free((genericptr_t) EPRI(mtmp)); + EPRI(mtmp) = (struct epri *) 0; + } + mtmp->ispriest = 0; +} +void +neweshk(struct monst* mtmp) +{ + if (!mtmp->mextra) + mtmp->mextra = newmextra(); + if (!ESHK(mtmp)) + ESHK(mtmp) = (struct eshk *) alloc(sizeof(struct eshk)); + (void) memset((genericptr_t) ESHK(mtmp), 0, sizeof(struct eshk)); + ESHK(mtmp)->bill_p = (struct bill_x *) 0; +} + +void +free_eshk(struct monst* mtmp) +{ + if (mtmp->mextra && ESHK(mtmp)) { + free((genericptr_t) ESHK(mtmp)); + ESHK(mtmp) = (struct eshk *) 0; + } + mtmp->isshk = 0; +} + +void +newemin(struct monst *mtmp) +{ + if (!mtmp->mextra) + mtmp->mextra = newmextra(); + if (!EMIN(mtmp)) { + EMIN(mtmp) = (struct emin *) alloc(sizeof(struct emin)); + (void) memset((genericptr_t) EMIN(mtmp), 0, sizeof(struct emin)); + } +} + +void +free_emin(struct monst *mtmp) +{ + if (mtmp->mextra && EMIN(mtmp)) { + free((genericptr_t) EMIN(mtmp)); + EMIN(mtmp) = (struct emin *) 0; + } + mtmp->isminion = 0; +} + +void +newedog(struct monst *mtmp) +{ + if (!mtmp->mextra) + mtmp->mextra = newmextra(); + if (!EDOG(mtmp)) { + EDOG(mtmp) = (struct edog *) alloc(sizeof(struct edog)); + (void) memset((genericptr_t) EDOG(mtmp), 0, sizeof(struct edog)); + } +} + +void +free_edog(struct monst *mtmp) +{ + if (mtmp->mextra && EDOG(mtmp)) { + free((genericptr_t) EDOG(mtmp)); + EDOG(mtmp) = (struct edog *) 0; + } + mtmp->mtame = 0; +} + +void +newebones(struct monst *mtmp) +{ + if (!mtmp->mextra) + mtmp->mextra = newmextra(); + if (!EBONES(mtmp)) { + EBONES(mtmp) = (struct ebones *) alloc(sizeof(struct ebones)); + (void) memset((genericptr_t) EBONES(mtmp), 0, sizeof(struct ebones)); + } +} + +void +free_ebones(struct monst *mtmp) +{ + if (mtmp->mextra && EBONES(mtmp)) { + free((genericptr_t) EBONES(mtmp)); + EBONES(mtmp) = (struct ebones *) 0; + } +} + +static const struct mextra zeromextra = DUMMY; + +static void +init_mextra(struct mextra *mex) +{ + *mex = zeromextra; + mex->mcorpsenm = NON_PM; +} + +struct mextra * +newmextra(void) +{ + struct mextra *mextra; + + mextra = (struct mextra *) alloc(sizeof(struct mextra)); + init_mextra(mextra); + return mextra; +} + +void +newomonst(struct obj* otmp) +{ + if (!otmp->oextra) + otmp->oextra = newoextra(); + + if (!OMONST(otmp)) { + struct monst *m = newmonst(); + + *m = cg.zeromonst; + OMONST(otmp) = m; + } +} + +void +free_omonst(struct obj* otmp) +{ + if (otmp->oextra) { + struct monst *m = OMONST(otmp); + + if (m) { + if (m->mextra) + dealloc_mextra(m); + free((genericptr_t) m); + OMONST(otmp) = (struct monst *) 0; + } + } +} + +void +newomid(struct obj* otmp) +{ + if (!otmp->oextra) + otmp->oextra = newoextra(); + OMID(otmp) = 0; +} + +void +free_omid(struct obj* otmp) +{ + OMID(otmp) = 0; +} + +void +new_omailcmd(struct obj* otmp, const char * response_cmd) +{ + if (!otmp->oextra) + otmp->oextra = newoextra(); + if (OMAILCMD(otmp)) + free_omailcmd(otmp); + OMAILCMD(otmp) = dupstr(response_cmd); +} + +void +free_omailcmd(struct obj* otmp) +{ + if (otmp->oextra && OMAILCMD(otmp)) { + free((genericptr_t) OMAILCMD(otmp)); + OMAILCMD(otmp) = (char *) 0; + } +} + +static const struct oextra zerooextra = DUMMY; + +static void +init_oextra(struct oextra* oex) +{ + *oex = zerooextra; +} + + +struct oextra * +newoextra(void) +{ + struct oextra *oextra; + + oextra = (struct oextra *) alloc(sizeof (struct oextra)); + init_oextra(oextra); + return oextra; +} + +void +dealloc_mextra(struct monst* m) +{ + struct mextra *x = m->mextra; + + if (x) { + if (x->mgivenname) + free((genericptr_t) x->mgivenname); + if (x->egd) + free((genericptr_t) x->egd); + if (x->epri) + free((genericptr_t) x->epri); + if (x->eshk) + free((genericptr_t) x->eshk); + if (x->emin) + free((genericptr_t) x->emin); + if (x->edog) + free((genericptr_t) x->edog); + if (x->ebones) + free((genericptr_t) x->ebones); + /* [no action needed for x->mcorpsenm] */ + + free((genericptr_t) x); + m->mextra = (struct mextra *) 0; + } +} + +void +dealloc_monst(struct monst* mon) +{ + if (mon->mextra) + dealloc_mextra(mon); + free((genericptr_t) mon); +} + +/* allocate space for an object's name; removes old name if there is one */ +void +new_oname(struct obj *obj, + int lth) /* desired length (caller handles adding 1 + for terminator) */ +{ + if (lth) { + /* allocate oextra if necessary; otherwise get rid of old name */ + if (!obj->oextra) + obj->oextra = newoextra(); + else + free_oname(obj); /* already has oextra, might also have name */ + ONAME(obj) = (char *) alloc((unsigned) lth); + } else { + /* zero length: the new name is empty; get rid of the old name */ + if (has_oname(obj)) + free_oname(obj); + } +} + +/* release an object's name; retains oextra even if all fields are now null */ +void +free_oname(struct obj *obj) +{ + if (has_oname(obj)) { + free((genericptr_t) ONAME(obj)); + ONAME(obj) = (char *) 0; + } +} + +#ifdef WIN32 +void +win32_abort(void) +{ + abort(); +} +#endif + +static int +length_without_val(const char *user_string, int len) +{ + const char *p = strchr(user_string, ':'), *q = strchr(user_string, '='); + + if (!p || (q && q < p)) + p = q; + if (p) { + /* 'user_string' hasn't necessarily been through mungspaces() + so might have tabs or consecutive spaces */ + while (p > user_string && isspace((uchar) * (p - 1))) + p--; + len = (int) (p - user_string); + } + return len; +} + +/* check whether a user-supplied option string is a proper leading + substring of a particular option name; option string might have + a colon or equals sign and arbitrary value appended to it */ +boolean +match_optname(const char *user_string, const char *optn_name, int min_length, + boolean val_allowed) +{ + int len = (int) strlen(user_string); + + if (val_allowed) + len = length_without_val(user_string, len); + + return (boolean) (len >= min_length + && !strncmpi(optn_name, user_string, len)); +} + +/* sfctool.c */ diff --git a/util/sfexpasc.c b/util/sfexpasc.c new file mode 100644 index 000000000..f129efe6c --- /dev/null +++ b/util/sfexpasc.c @@ -0,0 +1,1296 @@ +/* NetHack 3.7 sfexpasc.c.c $NHDT-Date$ $NHDT-Branch$:$NHDT-Revision$ */ +/* Copyright (c) Michael Allison, 2025. */ +/* NetHack may be freely redistributed. See license for details. */ + +/* avoid the global.h define */ +#define STRNCMPI + +#include "hack.h" +#include "integer.h" +#include "sfprocs.h" +#include "sfproto.h" + +#if defined(MACOSX) || defined(VMS) +extern long long atoll(const char *); +#endif + +static void put_savefield(NHFILE *, char *, size_t); +char *get_savefield(NHFILE *, char *, size_t); +#ifdef SAVEFILE_DEBUGGING +void report_problem_exportascii(NHFILE *, const char *, const char *, + const char *); +#endif + +#ifdef _MSC_VER +#define strcmpi _stricmp +#else +#define strcmpi strcasecmp +#endif + +static char linebuf[BUFSZ * 10]; +static char outbuf[BUFSZ * 10]; + +#if 0 +void exportascii_sfo_any(NHFILE *nhfp, union any *d_any, const char *myname UNUSED); +void exportascii_sfi_any(NHFILE *nhfp, union any *d_any, const char *myname UNUSED); +void exportascii_sfo_aligntyp(NHFILE *nhfp, aligntyp *d_aligntyp, const char *myname UNUSED); +void exportascii_sfo_bitfield(NHFILE *nhfp, uint8_t *d_bitfield, const char *myname UNUSED, int); +void exportascii_sfo_boolean(NHFILE *nhfp, boolean *d_boolean, const char *myname UNUSED); +void exportascii_sfo_genericptr(NHFILE *nhfp, genericptr_t *d_genericptr, const char *myname UNUSED); +void exportascii_sfo_int32(NHFILE *nhfp, int *d_int, const char *myname UNUSED); +void exportascii_sfo_long(NHFILE *nhfp, long *d_long, const char *myname UNUSED); +void exportascii_sfo_schar(NHFILE *nhfp, schar *d_schar, const char *myname UNUSED); +void exportascii_sfo_int16(NHFILE *nhfp, short *d_short, const char *myname UNUSED); +void exportascii_sfo_size_t(NHFILE *nhfp, size_t *d_size_t, const char *myname UNUSED); +void exportascii_sfo_time_t(NHFILE *nhfp, time_t *d_time_t, const char *myname UNUSED); +void exportascii_sfo_uint32(NHFILE *nhfp, unsigned *d_unsigned, const char *myname); +void exportascii_sfo_uint(NHFILE *nhfp, unsigned *d_unsigned, const char *myname); +void exportascii_sfo_uchar(NHFILE *nhfp, unsigned char *d_uchar, const char *myname UNUSED); +void exportascii_sfo_uint(NHFILE *nhfp, unsigned int *d_uint, const char *myname UNUSED); +void exportascii_sfo_ulong(NHFILE *nhfp, unsigned long *d_ulong, const char *myname UNUSED); +void exportascii_sfo_ushort(NHFILE *nhfp, unsigned short *d_ushort, const char *myname UNUSED); +void exportascii_sfo_coordxy(NHFILE *nhfp, coordxy *d_coordxy, const char *myname UNUSED); +void exportascii_sfo_char(NHFILE *nhfp, xint8 *d_xint8, const char *myname UNUSED); +void exportascii_sfo_xint16(NHFILE *nhfp, xint16 *d_xint16, const char *myname UNUSED); +void exportascii_sfo_char(NHFILE *nhfp, char *d_str, const char *myname UNUSED, int cnt); +void exportascii_sfo_addinfo(NHFILE *nhfp UNUSED, const char *parent UNUSED, const char *action UNUSED, const char *myname UNUSED, int indx UNUSED); +void exportascii_sfi_aligntyp(NHFILE *nhfp, aligntyp *d_aligntyp, const char *myname UNUSED); +void exportascii_sfi_bitfield(NHFILE *nhfp, uint8_t *d_bitfield, const char *myname UNUSED, int); +void exportascii_sfi_boolean(NHFILE *nhfp, boolean *d_boolean, const char *myname UNUSED); +void exportascii_sfi_genericptr(NHFILE *nhfp, genericptr_t *d_genericptr, const char *myname UNUSED); +void exportascii_sfi_int32(NHFILE *nhfp, int *d_int, const char *myname UNUSED); +void exportascii_sfi_long(NHFILE *nhfp, long *d_long, const char *myname UNUSED); +void exportascii_sfi_schar(NHFILE *nhfp, schar *d_schar, const char *myname UNUSED); +void exportascii_sfi_int16(NHFILE *nhfp, short *d_short, const char *myname UNUSED); +void exportascii_sfi_size_t(NHFILE *nhfp, size_t *d_size_t, const char *myname UNUSED); +void exportascii_sfi_time_t(NHFILE *nhfp, time_t *d_time_t, const char *myname UNUSED); +void exportascii_sfi_uint32(NHFILE *nhfp, unsigned *d_unsigned, const char *myname); +void exportascii_sfi_uint(NHFILE *nhfp, unsigned *d_unsigned, const char *myname); +void exportascii_sfi_uchar(NHFILE *nhfp, unsigned char *d_uchar, const char *myname UNUSED); +void exportascii_sfi_uint(NHFILE *nhfp, unsigned int *d_uint, const char *myname UNUSED); +void exportascii_sfi_ulong(NHFILE *nhfp, unsigned long *d_ulong, const char *myname UNUSED); +void exportascii_sfi_ushort(NHFILE *nhfp, unsigned short *d_ushort, const char *myname UNUSED); +void exportascii_sfi_coordxy(NHFILE *nhfp, coordxy *d_coordxy, const char *myname UNUSED); +void exportascii_sfi_xint8(NHFILE *nhfp, xint8 *d_xint8, const char *myname UNUSED); +void exportascii_sfi_xint16(NHFILE *nhfp, xint16 *d_xint16, const char *myname UNUSED); +void exportascii_sfi_cnt(NHFILE *nhfp, char *d_str, const char *myname UNUSED, int cnt); +#endif + +#define SFO_BODY(dt) \ +{ \ +} + +#define SFI_BODY(dt) \ +{ \ +} + +#define SF_A(dtyp) \ +void exportascii_sfo_##dtyp(NHFILE *, dtyp *d_##dtyp, \ + const char *); \ +void exportascii_sfi_##dtyp(NHFILE *, dtyp *d_##dtyp, \ + const char *); + +/* +void exportascii_sfo_##dtyp(NHFILE *nhfp, dtyp *d_##dtyp, \ + const char *myname UNUSED) \ + SFO_BODY(dtyp) \ + \ +void exportascii_sfi_##dtyp(NHFILE *nhfp, dtyp *d_##dtyp, \ + const char *myname UNUSED) \ + SFI_BODY(dtyp) +*/ + +#define SF_C(keyw, dtyp) \ +void exportascii_sfo_##dtyp(NHFILE * UNUSED, keyw dtyp *d_##dtyp UNUSED, \ + const char *); \ +void exportascii_sfi_##dtyp(NHFILE *UNUSED, keyw dtyp *d_##dtyp, \ + const char *); \ + \ +void exportascii_sfo_##dtyp(NHFILE *nhfp UNUSED, keyw dtyp *d_##dtyp UNUSED, \ + const char *myname UNUSED) \ + SFO_BODY(dtyp) \ + \ +void exportascii_sfi_##dtyp(NHFILE *nhfp UNUSED, keyw dtyp *d_##dtyp UNUSED, \ + const char *myname UNUSED) \ + SFI_BODY(dtyp) + + +#define SF_X(xxx, dtyp) \ +void exportascii_sfo_##dtyp(NHFILE * UNUSED, xxx *d_##dtyp UNUSED, \ + const char * UNUSED); \ +void exportascii_sfi_##dtyp(NHFILE *, xxx *d_##dtyp, \ + const char *); \ + \ +void exportascii_sfo_##dtyp(NHFILE *nhfp UNUSED, xxx *d_##dtyp UNUSED, \ + const char *myname UNUSED) \ + SFO_BODY(dtyp) \ + \ +void exportascii_sfi_##dtyp(NHFILE *nhfp, xxx *d_##dtyp, \ + const char *myname UNUSED) \ + SFI_BODY(dtyp) + + +#define SF_BF(xxx, dtyp) \ +void exportascii_sfo_##dtyp(NHFILE *, xxx *d_##dtyp, \ + const char *, int); \ +void exportascii_sfi_##dtyp(NHFILE *, xxx *d_##dtyp, \ + const char *, int); + +SF_C(struct, arti_info) +SF_C(struct, nhrect) +SF_C(struct, branch) +SF_C(struct, bubble) +SF_C(struct, cemetery) +SF_C(struct, context_info) +SF_C(struct, nhcoord) +SF_C(struct, damage) +SF_C(struct, dest_area) +SF_C(struct, dgn_topology) +SF_C(struct, dungeon) +SF_C(struct, d_level) +SF_C(struct, ebones) +SF_C(struct, edog) +SF_C(struct, egd) +SF_C(struct, emin) +SF_C(struct, engr) +SF_C(struct, epri) +SF_C(struct, eshk) +SF_C(struct, fe) +SF_C(struct, flag) +SF_C(struct, fruit) +SF_C(struct, gamelog_line) +SF_C(struct, kinfo) +SF_C(struct, levelflags) +SF_C(struct, ls_t) +SF_C(struct, linfo) +SF_C(struct, mapseen_feat) +SF_C(struct, mapseen_flags) +SF_C(struct, mapseen_rooms) +SF_C(struct, mkroom) +SF_C(struct, monst) +SF_C(struct, mvitals) +SF_C(struct, obj) +SF_C(struct, objclass) +SF_C(struct, q_score) +SF_C(struct, rm) +SF_C(struct, spell) +SF_C(struct, stairway) +SF_C(struct, s_level) +SF_C(struct, trap) +SF_C(struct, version_info) +SF_C(struct, you) +/* SF_C(union, any) */ +void exportascii_sfo_any(NHFILE *nhfp, union any *d_any, const char *myname UNUSED); +void exportascii_sfi_any(NHFILE *nhfp, union any *d_any, const char *myname UNUSED); + +SF_A(aligntyp) +SF_A(boolean) +SF_A(coordxy) +SF_A(genericptr) +SF_A(int) +SF_A(int16) +SF_A(int32) +SF_A(int64) +SF_A(long) +SF_A(schar) +SF_A(short) +SF_A(size_t) +SF_A(time_t) +SF_A(uchar) +SF_A(uint16) +SF_A(uint32) +SF_A(uint64) +SF_A(ulong) +SF_A(unsigned) +SF_A(ushort) +SF_A(xint16) +SF_A(xint8) +void exportascii_sfo_char(NHFILE *nhfp, char *d_char, const char *myname UNUSED, int cnt); +void exportascii_sfi_char(NHFILE *nhfp, char *d_char, const char *myname UNUSED, int cnt); +void exportascii_sfo_bitfield(NHFILE *nhfp, uint8_t *d_bitfield, + const char *myname UNUSED, int bflen UNUSED); +void exportascii_sfi_bitfield(NHFILE *nhfp, uint8_t *d_bitfield, + const char *myname UNUSED, int bflen UNUSED); +int critical_members_count_core(NHFILE *nhfp); + + +/* + *---------------------------------------------------------------------------- + * Sfo_def_ routines + * + * Default output routines. + * + *---------------------------------------------------------------------------- + */ + + +void +exportascii_sfo_any(NHFILE *nhfp, union any *d_any, const char *myname UNUSED) +{ + /* const char *parent = "any"; */ + + /* nhUse(parent); */ + Sprintf(outbuf, "%llx", (unsigned long long) d_any->a_void); + put_savefield(nhfp, outbuf, sizeof outbuf); + + Sprintf(outbuf, "%lu", d_any->a_ulong); + put_savefield(nhfp, outbuf, sizeof outbuf); + + Sprintf(outbuf, "%ld", d_any->a_long); + put_savefield(nhfp, outbuf, sizeof outbuf); + + Sprintf(outbuf, "%d", d_any->a_uint); + put_savefield(nhfp, outbuf, sizeof outbuf); + + Sprintf(outbuf, "%d", d_any->a_int);; + put_savefield(nhfp, outbuf, sizeof outbuf); + + Sprintf(outbuf, "%hd", (short) d_any->a_char); + put_savefield(nhfp, outbuf, sizeof outbuf); + +#if 0 + Sfo_genericptr(nhfp, d_any->a_void, parent, "a_void", 1); /* (genericptr_t) */ + Sfo_genericptr(nhfp, d_any->a_obj, parent, "a_obj", 1); /* (struct obj *) */ + Sfo_genericptr(nhfp, d_any->a_monst, parent, "a_monst", 1); /* (struct monst *) */ + Sfo_int32(nhfp, &d_any->a_int, parent, "a_int", 1); /* (int) */ + Sfo_char(nhfp, &d_any->a_char, parent, "a_char", 1); /* (char) */ + Sfo_schar(nhfp, &d_any->a_schar, parent, "a_schar", 1); /* (schar) */ + Sfo_uchar(nhfp, &d_any->a_uchar, parent, "a_uchar", 1); /* (uchar) */ + Sfo_uint(nhfp, &d_any->a_uint, parent, "a_uint", 1); /* (unsigned int) */ + Sfo_long(nhfp, &d_any->a_long, parent, "a_long", 1); /* (long) */ + Sfo_ulong(nhfp, &d_any->a_ulong, parent, "a_ulong", 1); /* (unsigned long) */ + Sfo_genericptr(nhfp, d_any->a_iptr, parent, "a_iptr", 1); /* (int *) */ + Sfo_genericptr(nhfp, d_any->a_lptr, parent, "a_lptr", 1); /* (long *) */ + Sfo_genericptr(nhfp, d_any->a_ulptr, parent, "a_ulptr", 1); /* (unsigned long *) */ + Sfo_genericptr(nhfp, d_any->a_uptr, parent, "a_uptr", 1); /* (unsigned *) */my + Sfo_genericptr(nhfp, d_any->a_string, parent, "a_string", 1); /* (const char *) */ + Sfo_ulong(nhfp, &d_any->a_mask32, parent, "a_mask32", 1); /* (unsigned long) */ +#endif +} + +void +exportascii_sfo_aligntyp(NHFILE *nhfp, aligntyp *d_aligntyp, const char *myname UNUSED) +{ + int itmp; + itmp = (int) *d_aligntyp; + Sprintf(outbuf, "%d", (short) itmp); + put_savefield(nhfp, outbuf, sizeof outbuf); +} + +void +exportascii_sfo_bitfield(NHFILE *nhfp, uint8_t *d_bitfield, const char *myname UNUSED, int bflen UNUSED) +{ + /* for bitfields, cnt is the number of bits, not an array */ + Sprintf(outbuf, "%hu", (unsigned short) *d_bitfield); + put_savefield(nhfp, outbuf, sizeof outbuf); +} + +void +exportascii_sfo_boolean(NHFILE *nhfp, boolean *d_boolean, const char *myname UNUSED) +{ + if (nhfp->fpdebug) + fprintf(nhfp->fpdebug, "(%s)\n", (*d_boolean) ? "TRUE" : "FALSE"); + Sprintf(outbuf, "%s", *d_boolean ? "true" : "false"); + put_savefield(nhfp, outbuf, sizeof outbuf); + d_boolean++; +} + +void exportascii_sfo_genericptr(NHFILE *nhfp, genericptr_t *d_genericptr, + const char *myname UNUSED); + +void +exportascii_sfo_genericptr(NHFILE *nhfp, genericptr_t *d_genericptr, const char *myname UNUSED) +{ + unsigned long tmp; + char *byteptr = (char *) d_genericptr; + /* + * sbrooms is an array of pointers to mkroom. + * That array dimension is MAX_SUBROOMS. + * Even though the pointers themselves won't + * be valid, we need to account for the existence + * of that array and perhaps zero or non-zero. + */ + tmp = (*d_genericptr) ? 1UL : 0UL; + Sprintf(outbuf, "%08lu", tmp); + put_savefield(nhfp, outbuf, sizeof outbuf); + byteptr += sizeof(void *); + d_genericptr = (genericptr_t) byteptr; +} + +#if 0 +void +exportascii_sfo_int32(NHFILE *nhfp, int *d_int, const char *myname UNUSED) +{ + Sprintf(outbuf, "%d", *d_int); + put_savefield(nhfp, outbuf, sizeof outbuf); + d_int++; +} +#endif + +void +exportascii_sfo_long(NHFILE *nhfp, long *d_long, const char *myname UNUSED) +{ + Sprintf(outbuf, "%ld", *d_long); + put_savefield(nhfp, outbuf, sizeof outbuf); + d_long++; +} + +void +exportascii_sfo_schar(NHFILE *nhfp, schar *d_schar, const char *myname UNUSED) +{ + int itmp; + itmp = (int) *d_schar; + Sprintf(outbuf, "%d", itmp); + put_savefield(nhfp, outbuf, sizeof outbuf); + d_schar++; +} + +void +exportascii_sfo_int16(NHFILE *nhfp, short *d_short, const char *myname UNUSED) +{ + Sprintf(outbuf, "%hd", *d_short); + put_savefield(nhfp, outbuf, sizeof outbuf); + d_short++; +} + +void +exportascii_sfo_size_t(NHFILE *nhfp, size_t *d_size_t, const char *myname UNUSED) +{ + unsigned long ul = (unsigned long) *d_size_t; + + Sprintf(outbuf, "%lu", ul); + put_savefield(nhfp, outbuf, sizeof outbuf); + d_size_t++; +} + +void +exportascii_sfo_time_t(NHFILE *nhfp, time_t *d_time_t, const char *myname UNUSED) +{ + Sprintf(outbuf, "%s", yyyymmddhhmmss(*d_time_t)); + put_savefield(nhfp, outbuf, sizeof outbuf); +} +void +exportascii_sfo_xint8(NHFILE *nhfp, int8 *d_int8, const char *myname UNUSED) +{ + Sprintf(outbuf, "%d", (int) *d_int8); + put_savefield(nhfp, outbuf, sizeof outbuf); + d_int8++; +} +#if 0 +void +exportascii_sfo_int16(NHFILE *nhfp, int16 *d_int16, const char *myname UNUSED) +{ + Sprintf(outbuf, "%d", (int) *d_int16); + put_savefield(nhfp, outbuf, sizeof outbuf); + d_uint16++; +} +#endif + +#if 0 +void +exportascii_sfo_char(NHFILE *nhfp, xint8 *d_xint8, const char *myname UNUSED, int cnt) +{ + short tmp; + + tmp = (int) *d_xint8; + Sprintf(outbuf, "%d", tmp); + put_savefield(nhfp, outbuf, sizeof outbuf); + d_xint8++; +} +#endif + +void +exportascii_sfo_int32(NHFILE *nhfp, int32 *d_int32, const char *myname UNUSED) +{ + Sprintf(outbuf, "%d", *d_int32); + put_savefield(nhfp, outbuf, sizeof outbuf); + d_int32++; +} + +void +exportascii_sfo_int64(NHFILE *nhfp, int64 *d_int64, const char *myname UNUSED) +{ + Sprintf(outbuf, "%lld", (long long) *d_int64); + put_savefield(nhfp, outbuf, sizeof outbuf); + d_int64++; +} + +void +exportascii_sfo_int(NHFILE *nhfp, int *d_int, const char *myname UNUSED) +{ + Sprintf(outbuf, "%d", *d_int); + put_savefield(nhfp, outbuf, sizeof outbuf); + d_int++; +} +void +exportascii_sfo_short(NHFILE *nhfp, short *d_short, const char *myname UNUSED) +{ + Sprintf(outbuf, "%d", (int) *d_short); + put_savefield(nhfp, outbuf, sizeof outbuf); + d_short++; +} +/* aka exportascii_sfo_uint8 */ +void +exportascii_sfo_uchar(NHFILE *nhfp, unsigned char *d_uchar, const char *myname UNUSED) +{ + unsigned x_uint32 = (uint32) *d_uchar; + + Sprintf(outbuf, "%u", x_uint32); + put_savefield(nhfp, outbuf, sizeof outbuf); + d_uchar++; +} + +void +exportascii_sfo_uint16(NHFILE *nhfp, uint16 *d_uint16, const char *myname UNUSED) +{ + Sprintf(outbuf, "%u", (uint32) *d_uint16); + put_savefield(nhfp, outbuf, sizeof outbuf); + d_uint16++; +} + +void +exportascii_sfo_uint32(NHFILE *nhfp, uint32 *d_uint32, const char *myname UNUSED) +{ + Sprintf(outbuf, "%u", *d_uint32); + put_savefield(nhfp, outbuf, sizeof outbuf); + d_uint32++; +} + +void +exportascii_sfo_uint64(NHFILE *nhfp, uint64 *d_uint64, const char *myname UNUSED) +{ + Sprintf(outbuf, "%llu", (unsigned long long) *d_uint64); + put_savefield(nhfp, outbuf, sizeof outbuf); + d_uint64++; +} + +void +exportascii_sfo_ulong(NHFILE *nhfp, unsigned long *d_ulong, const char *myname UNUSED) +{ + Sprintf(outbuf, "%lu", *d_ulong); + put_savefield(nhfp, outbuf, sizeof outbuf); + d_ulong++; +} + + +void +exportascii_sfo_ushort(NHFILE *nhfp, unsigned short *d_ushort, const char *myname UNUSED) +{ + Sprintf(outbuf, "%hu", *d_ushort); + put_savefield(nhfp, outbuf, sizeof outbuf); + d_ushort++; +} + +void +exportascii_sfo_unsigned(NHFILE *nhfp, unsigned *d_unsigned, const char *myname UNUSED) +{ + Sprintf(outbuf, "%u", *d_unsigned); + put_savefield(nhfp, outbuf, sizeof outbuf); + d_unsigned++; +} + +void +exportascii_sfo_coordxy(NHFILE *nhfp, coordxy *d_coordxy, const char *myname UNUSED) +{ + short tmp; + + tmp = (short) *d_coordxy; + Sprintf(outbuf, "%hu", tmp); + put_savefield(nhfp, outbuf, sizeof outbuf); + d_coordxy++; +} + + +void +exportascii_sfo_xint16(NHFILE *nhfp, xint16 *d_xint16, const char *myname UNUSED) +{ + short tmp; + + tmp = (short) *d_xint16; + Sprintf(outbuf, "%hu", tmp); + put_savefield(nhfp, outbuf, sizeof outbuf); + d_xint16++; +} + +static char strbuf[BUFSZ * 10]; + +void +exportascii_sfo_char(NHFILE *nhfp, char *d_char, const char *myname UNUSED, int cnt) +{ + int i, j; + uint uintval; + char sval[QBUFSZ]; + uchar *usrc = (uchar *) d_char, *udest = (uchar *)strbuf; + + /* cnt is the number of characters */ + for (i = 0; i < cnt; ++i) { + if ((*usrc < 32) || (*usrc == '\\') || (*usrc == '|')) { + *udest++ = '\\'; + uintval = *usrc++; + Sprintf(sval, "%03u", uintval); + for (j = 0; j < 3; ++j) + *udest++ = (uchar) sval[j]; + } else { + *udest++ = *usrc++; + } + } + *udest = '\0'; + put_savefield(nhfp, strbuf, strlen(strbuf)); +} + +static void +put_savefield(NHFILE *nhfp, char *obuf, size_t outbufsz UNUSED) +{ + nhfp->wcount++; + fprintf(nhfp->fpdef, "%07ld|%s\n", nhfp->wcount, obuf); + fflush(nhfp->fpdef); +} + +/* + *---------------------------------------------------------------------------- + * exportascii_sfi_ routines called from functions in Sfi_base.c + *---------------------------------------------------------------------------- + */ + +void exportascii_sfi_any(NHFILE *nhfp, union any *d_any, const char *myname UNUSED); + +void +exportascii_sfi_any(NHFILE *nhfp, union any *d_any, const char *myname UNUSED) +{ + char *rstr; + long long tmp; + + rstr = get_savefield(nhfp, linebuf, BUFSZ); + tmp = atoll(rstr); + d_any->a_uint64 = (uint64) tmp; + + rstr = get_savefield(nhfp, linebuf, BUFSZ); + tmp = atoll(rstr); + d_any->a_ulong = (unsigned long) tmp; + rstr = get_savefield(nhfp, linebuf, BUFSZ); + d_any->a_long = atol(rstr); + + rstr = get_savefield(nhfp, linebuf, BUFSZ); + tmp = atoll(rstr); + d_any->a_uint = (unsigned int) tmp; + + rstr = get_savefield(nhfp, linebuf, BUFSZ); + d_any->a_int = atoi(rstr); + + rstr = get_savefield(nhfp, linebuf, BUFSZ); + d_any->a_char = (char) atoi(rstr); + +#if 0 + Sfi_genericptr(nhfp, d_any->a_void, parent, "a_void", 1); + Sfi_genericptr(nhfp, d_any->a_obj, parent, "a_obj", 1); + Sfi_genericptr(nhfp, d_any->a_monst, parent, "a_monst", 1); + Sfi_int32(nhfp, &d_any->a_int, parent, "a_int", 1); + Sfi_char(nhfp, &d_any->a_char, parent, "a_char", 1); + Sfi_schar(nhfp, &d_any->a_schar, parent, "a_schar", 1); + Sfi_uchar(nhfp, &d_any->a_uchar, parent, "a_uchar", 1); + Sfi_uint(nhfp, &d_any->a_uint, parent, "a_uint", 1); + Sfi_long(nhfp, &d_any->a_long, parent, "a_long", 1); + Sfi_ulong(nhfp, &d_any->a_ulong, parent, "a_ulong", 1); + Sfi_genericptr(nhfp, d_any->a_iptr, parent, "a_iptr", 1); + Sfi_genericptr(nhfp, d_any->a_lptr, parent, "a_lptr", 1); + Sfi_genericptr(nhfp, d_any->a_ulptr, parent, "a_ulptr", 1); + Sfi_genericptr(nhfp, d_any->a_uptr, parent, "a_uptr", 1); + Sfi_genericptr(nhfp, d_any->a_string, parent, "a_string", 1); + Sfi_ulong(nhfp, &d_any->a_mask32, parent, "a_mask32", 1); +#endif +} + +void +exportascii_sfi_aligntyp(NHFILE *nhfp, aligntyp *d_aligntyp, const char *myname UNUSED) +{ + char *rstr; + aligntyp tmp; + long long lltmp; + + rstr = get_savefield(nhfp, linebuf, BUFSZ); + lltmp = atoll(rstr); + tmp = (aligntyp) lltmp; +#ifdef SAVEFILE_DEBUGGING + if (nhfp->structlevel && tmp != *d_aligntyp) + report_problem_ascii(nhfp, myparent, myname, parent); + else +#endif + *d_aligntyp = tmp; +} + +void +exportascii_sfi_bitfield(NHFILE *nhfp, uint8_t *d_bitfield, const char *myname UNUSED, int bflen UNUSED) +{ + char *rstr; + uint8_t tmp; + + /* cnt is the number of bits in the bitfield, not an array dimension */ + rstr = get_savefield(nhfp, linebuf, BUFSZ); + tmp = (uint8_t) atoi(rstr); +#ifdef SAVEFILE_DEBUGGING + if (nhfp->structlevel && tmp != *d_bitfield) + report_problem_ascii(nhfp, myparent, myname, parent); + else +#endif + *d_bitfield = tmp; +} + +void +exportascii_sfi_boolean(NHFILE *nhfp, boolean *d_boolean, const char *myname UNUSED) +{ + char *rstr; + + rstr = get_savefield(nhfp, linebuf, BUFSZ); +#ifdef SAVEFILE_DEBUGGING + if (!strcmpi(rstr, "false") && + !strcmpi(rstr, "true")) + report_problem_ascii(nhfp, myparent, myname, parent); + else +#endif + if (!strcmpi(rstr, "false")) + *d_boolean = FALSE; + else + *d_boolean = TRUE; + d_boolean++; +} + +void exportascii_sfi_genericptr(NHFILE *nhfp, genericptr_t *d_genericptr, + const char *myname UNUSED); + +void +exportascii_sfi_genericptr(NHFILE *nhfp, genericptr_t *d_genericptr, const char *myname UNUSED) +{ + long long lltmp; + char *rstr; + static const char *glorkum = "glorkum"; + + /* + * sbrooms is an array of pointers to mkroom. + * That array dimension is MAX_SUBROOMS. + * Even though the pointers themselves won't + * be valid, we need to account for the existence + * of that array. + */ + /* these pointers can't actually be valid */ + rstr = get_savefield(nhfp, linebuf, sizeof linebuf); + lltmp = atoll(rstr); + *d_genericptr = lltmp ? (genericptr_t) glorkum : (genericptr_t) 0; +} + +void +exportascii_sfi_int32(NHFILE *nhfp, int32 *d_int32, const char *myname UNUSED) +{ + int32 tmp; + char *rstr; + long ltmp; + + rstr = get_savefield(nhfp, linebuf, BUFSZ); + ltmp = atol(rstr); + tmp = (int32) ltmp; +#ifdef SAVEFILE_DEBUGGING + if (nhfp->structlevel && tmp != *d_int32) + report_problem_ascii(nhfp, myparent, myname, parent); + else +#endif + *d_int32 = (int32) tmp; + d_int32++; +} + +void +exportascii_sfi_int(NHFILE *nhfp, int *d_int, const char *myname UNUSED) +{ + int tmp; + char *rstr; + long ltmp; + + rstr = get_savefield(nhfp, linebuf, BUFSZ); + ltmp = atol(rstr); + tmp = (int) ltmp; +#ifdef SAVEFILE_DEBUGGING + if (nhfp->structlevel && tmp != *d_int) + report_problem_ascii(nhfp, myparent, myname, parent); + else +#endif + *d_int = (int32) tmp; + d_int++; +} +void +exportascii_sfi_long(NHFILE *nhfp, long *d_long, const char *myname UNUSED) +{ + long tmp; + long long lltmp; + char *rstr; + + rstr = get_savefield(nhfp, linebuf, BUFSZ); + lltmp = atoll(rstr); + tmp = (long) lltmp; +#ifdef SAVEFILE_DEBUGGING + if (nhfp->structlevel && tmp != *d_long) + report_problem_ascii(nhfp, myparent, myname, parent); + else +#endif + *d_long = tmp; + d_long++; +} + +void +exportascii_sfi_schar(NHFILE *nhfp, schar *d_schar, const char *myname UNUSED) +{ + schar tmp; + char *rstr; + + rstr = get_savefield(nhfp, linebuf, BUFSZ); + tmp = (schar) atoi(rstr); +#ifdef SAVEFILE_DEBUGGING + if (nhfp->structlevel && tmp != *d_schar) + report_problem_ascii(nhfp, myparent, myname, parent); + else +#endif + *d_schar = tmp; + d_schar++; +} + +void +exportascii_sfi_int16(NHFILE *nhfp, short *d_short, const char *myname UNUSED) +{ + short tmp; + char *rstr; + + rstr = get_savefield(nhfp, linebuf, BUFSZ); + tmp = (short) atoi(rstr); +#ifdef SAVEFILE_DEBUGGING + if (nhfp->structlevel && tmp != *d_short) + report_problem_ascii(nhfp, myparent, myname, parent); + else +#endif + *d_short = tmp; + d_short++; +} + +void +exportascii_sfi_int64(NHFILE *nhfp, int64 *d_int64, const char *myname UNUSED) +{ + int64 tmp; + char *rstr; + + rstr = get_savefield(nhfp, linebuf, BUFSZ); + tmp = (int64) atol(rstr); +#ifdef SAVEFILE_DEBUGGING + if (nhfp->structlevel && tmp != *d_int64) + report_problem_ascii(nhfp, myparent, myname, parent); + else +#endif + *d_int64 = tmp; + d_int64++; +} +void +exportascii_sfi_size_t(NHFILE *nhfp, size_t *d_size_t, const char *myname UNUSED) +{ + size_t tmp; + char *rstr; + + rstr = get_savefield(nhfp, linebuf, BUFSZ); + tmp = (size_t) atol(rstr); +#ifdef SAVEFILE_DEBUGGING + if (nhfp->structlevel && tmp != *d_size_t) + report_problem_ascii(nhfp, myparent, myname, parent); + else +#endif + *d_size_t = tmp; + d_size_t++; +} + +void +exportascii_sfi_time_t(NHFILE *nhfp, time_t *d_time_t, const char *myname UNUSED) +{ + time_t tmp; + char *rstr; + + rstr = get_savefield(nhfp, linebuf, BUFSZ); + tmp = time_from_yyyymmddhhmmss(rstr); +#ifdef SAVEFILE_DEBUGGING + if (nhfp->structlevel && tmp != *d_time_t) + report_problem_ascii(nhfp, myparent, myname, parent); + else +#endif + *d_time_t = tmp; + d_time_t++; +} + +#if 0 +void +exportascii_sfi_uint32(NHFILE *nhfp, unsigned *d_unsigned, const char *myname) +{ + /* deferal */ + exportascii_sfi_uint(nhfp, d_unsigned, myname); +} +#endif + +void +exportascii_sfi_uchar(NHFILE *nhfp, unsigned char *d_uchar, const char *myname UNUSED) +{ + uchar tmp; + int itmp; + char *rstr; + + rstr = get_savefield(nhfp, linebuf, BUFSZ); + itmp = atoi(rstr); + tmp = (char ) itmp; +#ifdef SAVEFILE_DEBUGGING + if (nhfp->structlevel && tmp != *d_uchar) + report_problem_ascii(nhfp, myparent, myname, parent); + else +#endif + *d_uchar = tmp; + d_uchar++; +} + +void +exportascii_sfi_uint16(NHFILE *nhfp, uint16 *d_uint16, const char *myname UNUSED) +{ + char *rstr; + unsigned int tmp; + long long lltmp; + + rstr = get_savefield(nhfp, linebuf, BUFSZ); + lltmp = atoll(rstr); + tmp = (unsigned int) lltmp; +#ifdef SAVEFILE_DEBUGGING + if (nhfp->structlevel && tmp != *d_uint) + report_problem_ascii(nhfp, myparent, myname, parent); + else +#endif + *d_uint16 = tmp; + d_uint16++; +} + +void +exportascii_sfi_uint32(NHFILE *nhfp, uint32 *d_uint32, const char *myname UNUSED) +{ + char *rstr; + uint32 tmp; + long long lltmp; + + rstr = get_savefield(nhfp, linebuf, BUFSZ); + lltmp = atoll(rstr); + tmp = (uint32) lltmp; +#ifdef SAVEFILE_DEBUGGING + if (nhfp->structlevel && tmp != *d_uint) + report_problem_ascii(nhfp, myparent, myname, parent); + else +#endif + *d_uint32 = tmp; + d_uint32++; +} + +void +exportascii_sfi_uint64(NHFILE *nhfp, uint64 *d_uint64, const char *myname UNUSED) +{ + char *rstr; + uint64 tmp; + long long lltmp; + + rstr = get_savefield(nhfp, linebuf, BUFSZ); + lltmp = atoll(rstr); + tmp = (uint64) lltmp; +#ifdef SAVEFILE_DEBUGGING + if (nhfp->structlevel && tmp != *d_uint) + report_problem_ascii(nhfp, myparent, myname, parent); + else +#endif + *d_uint64 = tmp; + d_uint64++; +} + +void +exportascii_sfi_unsigned(NHFILE *nhfp, unsigned *d_unsigned, const char *myname UNUSED) +{ + char *rstr; + uint32 tmp; + long long lltmp; + + rstr = get_savefield(nhfp, linebuf, BUFSZ); + lltmp = atoll(rstr); + tmp = (uint32) lltmp; +#ifdef SAVEFILE_DEBUGGING + if (nhfp->structlevel && tmp != *d_unsigned) + report_problem_ascii(nhfp, "", myname, parent); + else +#endif + *d_unsigned = tmp; + d_unsigned++; +} + +void +exportascii_sfi_ulong(NHFILE *nhfp, unsigned long *d_ulong, const char *myname UNUSED) +{ + unsigned long tmp; + long long lltmp; + char *rstr; + + rstr = get_savefield(nhfp, linebuf, BUFSZ); + lltmp = atoll(rstr); + tmp = (unsigned long) lltmp; +#ifdef SAVEFILE_DEBUGGING + if (nhfp->structlevel && tmp != *d_ulong) + report_problem_ascii(nhfp, myparent, myname, parent); + else +#endif + *d_ulong = tmp; + d_ulong++; +} + +void +exportascii_sfi_ushort(NHFILE *nhfp, unsigned short *d_ushort, const char *myname UNUSED) +{ + short tmp; + long long lltmp; + char *rstr; + + rstr = get_savefield(nhfp, linebuf, BUFSZ); + lltmp = atoll(rstr); + tmp = (unsigned short) lltmp; +#ifdef SAVEFILE_DEBUGGING + if (nhfp->structlevel && tmp != *d_ushort) + report_problem_ascii(nhfp, myparent, myname, parent); + else +#endif + *d_ushort = tmp; + d_ushort++; +} + +void +exportascii_sfi_coordxy(NHFILE *nhfp, coordxy *d_coordxy, const char *myname UNUSED) +{ + coordxy tmp; + int itmp; + char *rstr; + + rstr = get_savefield(nhfp, linebuf, BUFSZ); + itmp = atoi(rstr); + tmp = (coordxy) itmp; +#ifdef SAVEFILE_DEBUGGING + if (nhfp->structlevel && tmp != *d_coordxy) + report_problem_ascii(nhfp, myparent, myname, parent); + else +#endif + *d_coordxy = tmp; + d_coordxy++; +} + +void +exportascii_sfi_xint8(NHFILE *nhfp, xint8 *d_xint8, const char *myname UNUSED) +{ + xint8 tmp; + int itmp; + char *rstr; + + rstr = get_savefield(nhfp, linebuf, BUFSZ); + if (!nhfp->eof) { + itmp = atoi(rstr); + tmp = (xint8) itmp; + } else { + return; + } +#ifdef SAVEFILE_DEBUGGING + if (nhfp->structlevel && tmp != *d_xint8) + report_problem_ascii(nhfp, myparent, myname, parent); + else +#endif + *d_xint8 = tmp; + d_xint8++; +} + +void +exportascii_sfi_xint16(NHFILE *nhfp, xint16 *d_xint16, const char *myname UNUSED) +{ + xint16 tmp; + int itmp; + char *rstr; + + rstr = get_savefield(nhfp, linebuf, BUFSZ); + itmp = atoi(rstr); + tmp = (xint16) itmp; +#ifdef SAVEFILE_DEBUGGING + if (nhfp->structlevel && tmp != *d_xint16) + report_problem_ascii(nhfp, myparent, myname, parent); + else +#endif + *d_xint16 = tmp; + d_xint16++; +} + +void +exportascii_sfi_short(NHFILE *nhfp, short *d_short, const char *myname UNUSED) +{ + xint16 tmp; + int itmp; + char *rstr; + + rstr = get_savefield(nhfp, linebuf, BUFSZ); + itmp = atoi(rstr); + tmp = (xint16) itmp; +#ifdef SAVEFILE_DEBUGGING + if (nhfp->structlevel && tmp != *d_short) + report_problem_ascii(nhfp, "", myname, parent); + else +#endif + *d_short = tmp; + d_short++; +} + + +void +exportascii_sfi_char(NHFILE *nhfp, char *d_char, const char *myname UNUSED, int cnt) +{ + int i, j, sval; + char n[4], *rstr; + char *src, *dest; + + /* cnt is the length of the string */ + rstr = get_savefield(nhfp, strbuf, sizeof strbuf); + if (!rstr) { + nhfp->eof = TRUE; + return; + } + src = rstr; + dest = +#ifdef SAVEFILE_DEBUGGING + testbuf; +#else + d_char; +#endif + + for (i = 0; i < cnt; ++i) { + if (*src == '\\') { + src++; + for (j = 0; j < 4; ++j) { + if (j < 3) + n[j] = *src++; + else + n[j] = '\0'; + } + sval = atoi(n); + *dest++ = (char) sval; + } else + *dest++ = *src++; + } +#ifdef SAVEFILE_DEBUGGING + if (nhfp->structlevel) { + src = testbuf; + dest = d_char; + match = TRUE; + for (i = 0; i < cnt; ++i) { + if (*src++ != *dest++) + match = FALSE; + } + if (!match) + report_problem_ascii(nhfp, myparent, myname, parent); + else { + src = testbuf; + dest = d_char; + for (i = 0; i < cnt; ++i) + *dest++ = *src++; + } + } +#endif +} + +char * +get_savefield(NHFILE *nhfp, char *inbuf, size_t inbufsz) +{ + char *ep, *sep; + char *res = 0; + + if ((res =fgets(inbuf, (int) inbufsz, nhfp->fpdef)) != 0) { + nhfp->rcount++; + ep = strchr(inbuf, '\n'); + if (!ep) { /* newline missing */ + if (strlen(inbuf) < (inbufsz - 2)) { + /* likely the last line of file is just + missing a newline; process it anyway */ + ep = eos(inbuf); + } + } + if (ep) + *ep = '\0'; /* remove newline */ + sep = strchr(inbuf, '|'); + if (sep) + sep++; + + return sep; + } + inbuf[0] = '\0'; + nhfp->eof = TRUE; + return inbuf; +} + +#ifdef SAVEFILE_DEBUGGING +void +report_problem_ascii(NHFILE *nhfp, const char *s1, const char *s2, const char *s3) +{ + fprintf(nhfp->fpdebug, "faulty value preservation " + "(%ld, %s, %s, %s)\n", + ((nhfp->mode & READING) != 0) ? nhfp->rcount : nhfp->wcount, s1, s2, s3); +} +#endif + +int exportascii_critical_members_count(void); + +int +exportascii_critical_members_count(void) +{ + return 0; +} + +struct sf_fieldlevel_procs exportascii_sfo_procs = { + "exportascii", + /* sf_x */ + { + sfo_x_arti_info, + sfo_x_nhrect, + sfo_x_branch, + sfo_x_bubble, + sfo_x_cemetery, + sfo_x_context_info, + sfo_x_nhcoord, + sfo_x_damage, + sfo_x_dest_area, + sfo_x_dgn_topology, + sfo_x_dungeon, + sfo_x_d_level, + sfo_x_ebones, + sfo_x_edog, + sfo_x_egd, + sfo_x_emin, + sfo_x_engr, + sfo_x_epri, + sfo_x_eshk, + sfo_x_fe, + sfo_x_flag, + sfo_x_fruit, + sfo_x_gamelog_line, + sfo_x_kinfo, + sfo_x_levelflags, + sfo_x_ls_t, + sfo_x_linfo, + sfo_x_mapseen_feat, + sfo_x_mapseen_flags, + sfo_x_mapseen_rooms, + sfo_x_mkroom, + sfo_x_monst, + sfo_x_mvitals, + sfo_x_obj, + sfo_x_objclass, + sfo_x_q_score, + sfo_x_rm, + sfo_x_spell, + sfo_x_stairway, + sfo_x_s_level, + sfo_x_trap, + sfo_x_version_info, + sfo_x_you, + + exportascii_sfo_any, + exportascii_sfo_aligntyp, + exportascii_sfo_boolean, + exportascii_sfo_coordxy, + exportascii_sfo_genericptr, + exportascii_sfo_int, + exportascii_sfo_int16, + exportascii_sfo_int32, + exportascii_sfo_int64, + exportascii_sfo_long, + exportascii_sfo_schar, + exportascii_sfo_short, + exportascii_sfo_size_t, + exportascii_sfo_time_t, + exportascii_sfo_uchar, + exportascii_sfo_uint16, + exportascii_sfo_uint32, + exportascii_sfo_uint64, + exportascii_sfo_ulong, + exportascii_sfo_unsigned, + exportascii_sfo_ushort, + exportascii_sfo_xint16, + exportascii_sfo_xint8, + exportascii_sfo_char, + exportascii_sfo_bitfield, + } +}; + +struct sf_fieldlevel_procs exportascii_sfi_procs = { + "le", + /* sf_x */ + { + sfi_x_arti_info, + sfi_x_nhrect, + sfi_x_branch, + sfi_x_bubble, + sfi_x_cemetery, + sfi_x_context_info, + sfi_x_nhcoord, + sfi_x_damage, + sfi_x_dest_area, + sfi_x_dgn_topology, + sfi_x_dungeon, + sfi_x_d_level, + sfi_x_ebones, + sfi_x_edog, + sfi_x_egd, + sfi_x_emin, + sfi_x_engr, + sfi_x_epri, + sfi_x_eshk, + sfi_x_fe, + sfi_x_flag, + sfi_x_fruit, + sfi_x_gamelog_line, + sfi_x_kinfo, + sfi_x_levelflags, + sfi_x_ls_t, + sfi_x_linfo, + sfi_x_mapseen_feat, + sfi_x_mapseen_flags, + sfi_x_mapseen_rooms, + sfi_x_mkroom, + sfi_x_monst, + sfi_x_mvitals, + sfi_x_obj, + sfi_x_objclass, + sfi_x_q_score, + sfi_x_rm, + sfi_x_spell, + sfi_x_stairway, + sfi_x_s_level, + sfi_x_trap, + sfi_x_version_info, + sfi_x_you, + + exportascii_sfi_any, + exportascii_sfi_aligntyp, + exportascii_sfi_boolean, + exportascii_sfi_coordxy, + exportascii_sfi_genericptr, + exportascii_sfi_int, + exportascii_sfi_int16, + exportascii_sfi_int32, + exportascii_sfi_int64, + exportascii_sfi_long, + exportascii_sfi_schar, + exportascii_sfi_short, + exportascii_sfi_size_t, + exportascii_sfi_time_t, + exportascii_sfi_uchar, + exportascii_sfi_uint16, + exportascii_sfi_uint32, + exportascii_sfi_uint64, + exportascii_sfi_ulong, + exportascii_sfi_unsigned, + exportascii_sfi_ushort, + exportascii_sfi_xint16, + exportascii_sfi_xint8, + exportascii_sfi_char, + exportascii_sfi_bitfield, + } +}; diff --git a/util/sftags.c b/util/sftags.c new file mode 100644 index 000000000..cdb8f3a7a --- /dev/null +++ b/util/sftags.c @@ -0,0 +1,2230 @@ +/* NetHack 3.6 sftags.c $Date$ $Revision$ */ +/* Copyright (c) Michael Allison, 2025 */ +/* NetHack may be freely redistributed. See license for details. */ + +/* + * Read the given ctags file and generate: + * Intermediate temp files: + * include/sfo_proto.tmp + * include/sfi_proto.tmp + * util/sfi_data.tmp + * util/sfo_data.tmp + * util/sfnormalize.tmp + * Final files: + * sfdata.c + * sfproto.h + * + */ + +/* avoid global.h define */ +#define STRNCMPI + +#include "hack.h" +#include "integer.h" +#include "wintype.h" + +#ifdef __GNUC__ +#include +#define strncmpi strncasecmp +#define strcmpi strcasecmp +#elif defined(_MSC_VER) +#define strcmpi _stricmp +#ifndef strncmpi +#define strncmpi _strnicmp +#endif +#endif + +#if 0 +/* version information */ +#ifdef SHORT_FILENAMES +#include "patchlev.h" +#else +#include "patchlevel.h" +#endif +#endif + +#define NHTYPE_SIMPLE 1 +#define NHTYPE_COMPLEX 2 +struct nhdatatypes_t { + uint dtclass; + char *dtype; + size_t dtsize; +}; + +struct tagstruct { + uint marker; + int linenum; + char ptr[128]; + char tag[100]; + char filename[128]; + char searchtext[255]; + char tagtype; + char parent[100]; + char parenttype[100]; + char arraysize1[100]; + char arraysize2[100]; + struct tagstruct *next; +}; + +struct needs_array_handling { + const char *nm; + const char *parent; +}; + +#define SFO_DATA c_sfodata +#define SFI_DATA c_sfidata +#define SFDATATMP c_sfdatatmp +#define SFO_PROTO c_sfoproto +#define SFI_PROTO c_sfiproto +#define SFDATA c_sfdata +#define SFPROTO c_sfproto +#define SF_NORMALIZE_POINTERS c_sfnormalize +#define SFPROTO_NAME "../include/sfproto.h" +#define SFDATA_NAME "../util/sfdata.c" + +static char *fgetline(FILE*); +static void quit(void); +static void out_of_memory(void); +static void doline(char *); +static void chain(struct tagstruct *); +#if 0 +static void showthem(void); +static char *stripspecial(char *); +#endif +static char *deblank(char *); +static char *deeol(char *); +static void generate_c_files(void); +static char *findtype(char *, char *); +#if 0 +static boolean is_prim(char *); +#endif +static void taglineparse(char *, struct tagstruct *); +static void parseExtensionFields(struct tagstruct *, char *); +static void set_member_array_size(struct tagstruct *); +#if 0 +static char *member_array_dims(struct tagstruct *, char *); +static char *member_array_size(struct tagstruct *, char *); +#endif +static void output_types(FILE *); +#if 0 +static char *dtmacro(const char *,int); +#endif +static char *dtfn(const char *,int, boolean *); +static char *bfsize(const char *); +static char *fieldfix(char *,char *); +static boolean listed(struct tagstruct *t); +static const char *fn(const char *f); +static boolean no_x(const char *s); + +#ifdef VMS +static FILE *vms_fopen(name, mode) const char *name, *mode; +{ + return fopen(name, mode, "mbc=64", "shr=nil"); +} +# define fopen(f,m) vms_fopen(f,m) +#endif + +#define Fprintf (void) fprintf +#ifndef __GO32__ +#define DEFAULTTAGNAME "../util/sf.tags" +#else +#define DEFAULTTAGNAME "../util/sftags.tag" +#endif +#ifndef _MAX_PATH +#define _MAX_PATH 120 +#endif + +#define TAB '\t' +#define SPACE ' ' + +struct tagstruct *first; +struct tagstruct zerotag = { 0 }; + +static int tagcount; +static const char *infilenm; +static FILE *infile; +static char line[2048]; +static long lineno; +static char ssdef[BUFSZ]; +static char fieldfixbuf[BUFSZ]; +static boolean suppress_count; + +#define NHTYPE_SIMPLE 1 +#define NHTYPE_COMPLEX 2 + +struct nhdatatypes_t readtagstypes[] = { + { NHTYPE_SIMPLE, (char *) "any", sizeof(anything) }, + { NHTYPE_SIMPLE, (char *) "genericptr_t", sizeof(genericptr_t) }, + { NHTYPE_SIMPLE, (char *) "aligntyp", sizeof(aligntyp) }, + { NHTYPE_SIMPLE, (char *) "Bitfield", sizeof(uint8_t) }, + { NHTYPE_SIMPLE, (char *) "boolean", sizeof(boolean) }, + { NHTYPE_SIMPLE, (char *) "char", sizeof(char) }, + { NHTYPE_SIMPLE, (char *) "int", sizeof(int) }, + { NHTYPE_SIMPLE, (char *) "long", sizeof(long) }, + { NHTYPE_SIMPLE, (char *) "schar", sizeof(schar) }, + { NHTYPE_SIMPLE, (char *) "short", sizeof(short) }, + { NHTYPE_SIMPLE, (char *) "size_t", sizeof(size_t) }, + { NHTYPE_SIMPLE, (char *) "string", 1 }, + { NHTYPE_SIMPLE, (char *) "time_t", sizeof(time_t) }, + { NHTYPE_SIMPLE, (char *) "uchar", sizeof(uchar) }, + { NHTYPE_SIMPLE, (char *) "unsigned char", sizeof(unsigned char) }, + { NHTYPE_SIMPLE, (char *) "uint", sizeof(uint) }, + { NHTYPE_SIMPLE, (char *) "unsigned long", sizeof(unsigned long) }, + { NHTYPE_SIMPLE, (char *) "unsigned short", sizeof(unsigned short) }, + { NHTYPE_SIMPLE, (char *) "unsigned", sizeof(unsigned) }, + { NHTYPE_SIMPLE, (char *) "xint8", sizeof(xint8) }, + { NHTYPE_SIMPLE, (char *) "xint16", sizeof(xint16) }, + { NHTYPE_SIMPLE, (char *) "coordxy", sizeof(coordxy) }, + { NHTYPE_COMPLEX, (char *) "align", sizeof(struct align) }, + /* { NHTYPE_COMPLEX, (char *) "attack", sizeof(struct attack) }, */ + /* ^ permonst affil */ + { NHTYPE_COMPLEX, (char *) "arti_info", sizeof(struct arti_info) }, + { NHTYPE_COMPLEX, (char *) "attribs", sizeof(struct attribs) }, + { NHTYPE_COMPLEX, (char *) "bill_x", sizeof(struct bill_x) }, + { NHTYPE_COMPLEX, (char *) "branch", sizeof(struct branch) }, + { NHTYPE_COMPLEX, (char *) "bubble", sizeof(struct bubble) }, + { NHTYPE_COMPLEX, (char *) "cemetery", sizeof(struct cemetery) }, + /*{ NHTYPE_COMPLEX, (char *) "container", sizeof(struct container) }, */ + { NHTYPE_COMPLEX, (char *) "context_info", sizeof(struct context_info) }, + /* context sub-structures */ + { NHTYPE_COMPLEX, (char *) "achievement_tracking", + sizeof(struct achievement_tracking) }, + { NHTYPE_COMPLEX, (char *) "book_info", sizeof(struct book_info) }, + { NHTYPE_COMPLEX, (char *) "dig_info", + sizeof(struct dig_info) }, /* context */ + { NHTYPE_COMPLEX, (char *) "engrave_info", sizeof(struct engrave_info) }, + { NHTYPE_COMPLEX, (char *) "obj_split", sizeof(struct obj_split) }, + { NHTYPE_COMPLEX, (char *) "polearm_info", sizeof(struct polearm_info) }, + { NHTYPE_COMPLEX, (char *) "takeoff_info", sizeof(struct takeoff_info) }, + { NHTYPE_COMPLEX, (char *) "tin_info", sizeof(struct tin_info) }, + { NHTYPE_COMPLEX, (char *) "tribute_info", sizeof(struct tribute_info) }, + { NHTYPE_COMPLEX, (char *) "victual_info", sizeof(struct victual_info) }, + { NHTYPE_COMPLEX, (char *) "warntype_info", + sizeof(struct warntype_info) }, + /* end of context sub-structures */ + { NHTYPE_COMPLEX, (char *) "d_flags", sizeof(struct d_flags) }, + { NHTYPE_COMPLEX, (char *) "d_level", sizeof(struct d_level) }, + { NHTYPE_COMPLEX, (char *) "damage", sizeof(struct damage) }, + { NHTYPE_COMPLEX, (char *) "dest_area", sizeof(struct dest_area) }, + { NHTYPE_COMPLEX, (char *) "dgn_topology", sizeof(struct dgn_topology) }, + { NHTYPE_COMPLEX, (char *) "dungeon", sizeof(struct dungeon) }, + { NHTYPE_COMPLEX, (char *) "ebones", sizeof(struct ebones) }, + { NHTYPE_COMPLEX, (char *) "edog", sizeof(struct edog) }, + { NHTYPE_COMPLEX, (char *) "egd", sizeof(struct egd) }, + { NHTYPE_COMPLEX, (char *) "emin", sizeof(struct emin) }, + { NHTYPE_COMPLEX, (char *) "engr", sizeof(struct engr) }, + { NHTYPE_COMPLEX, (char *) "epri", sizeof(struct epri) }, + { NHTYPE_COMPLEX, (char *) "eshk", sizeof(struct eshk) }, + { NHTYPE_COMPLEX, (char *) "fakecorridor", sizeof(struct fakecorridor) }, + { NHTYPE_COMPLEX, (char *) "fe", sizeof(struct fe) }, + { NHTYPE_COMPLEX, (char *) "flag", sizeof(struct flag) }, + { NHTYPE_COMPLEX, (char *) "fruit", sizeof(struct fruit) }, + { NHTYPE_COMPLEX, (char *) "gamelog_line", sizeof(struct gamelog_line) }, + { NHTYPE_COMPLEX, (char *) "kinfo", sizeof(struct kinfo) }, + { NHTYPE_COMPLEX, (char *) "levelflags", sizeof(struct levelflags) }, + { NHTYPE_COMPLEX, (char *) "linfo", sizeof(struct linfo) }, + { NHTYPE_COMPLEX, (char *) "ls_t", sizeof(struct ls_t) }, + { NHTYPE_COMPLEX, (char *) "mapseen_feat", sizeof(struct mapseen_feat) }, + { NHTYPE_COMPLEX, (char *) "mapseen_flags", + sizeof(struct mapseen_flags) }, + { NHTYPE_COMPLEX, (char *) "mapseen_rooms", + sizeof(struct mapseen_rooms) }, + { NHTYPE_COMPLEX, (char *) "mapseen", sizeof(mapseen) }, + { NHTYPE_COMPLEX, (char *) "mextra", sizeof(struct mextra) }, + { NHTYPE_COMPLEX, (char *) "mkroom", sizeof(struct mkroom) }, + { NHTYPE_COMPLEX, (char *) "monst", sizeof(struct monst) }, + { NHTYPE_COMPLEX, (char *) "mvitals", sizeof(struct mvitals) }, + { NHTYPE_COMPLEX, (char *) "nhcoord", sizeof(struct nhcoord) }, + { NHTYPE_COMPLEX, (char *) "nhrect", sizeof(struct nhrect) }, + { NHTYPE_COMPLEX, (char *) "novel_tracking", + sizeof(struct novel_tracking) }, + { NHTYPE_COMPLEX, (char *) "obj", sizeof(struct obj) }, + { NHTYPE_COMPLEX, (char *) "objclass", sizeof(struct objclass) }, + { NHTYPE_COMPLEX, (char *) "oextra", sizeof(struct oextra) }, + /* {NHTYPE_COMPLEX, (char *) "permonst", sizeof(struct permonst)}, */ + { NHTYPE_COMPLEX, (char *) "prop", sizeof(struct prop) }, + { NHTYPE_COMPLEX, (char *) "q_score", sizeof(struct q_score) }, + { NHTYPE_COMPLEX, (char *) "rm", sizeof(struct rm) }, + { NHTYPE_COMPLEX, (char *) "s_level", sizeof(struct s_level) }, + { NHTYPE_COMPLEX, (char *) "skills", sizeof(struct skills) }, + { NHTYPE_COMPLEX, (char *) "spell", sizeof(struct spell) }, + { NHTYPE_COMPLEX, (char *) "stairway", sizeof(struct stairway) }, +#ifdef SYSFLAGS + { NHTYPE_COMPLEX, (char *) "sysflag", sizeof(struct sysflag) }, +#endif + { NHTYPE_COMPLEX, (char *) "trap", sizeof(struct trap) }, + /* {NHTYPE_COMPLEX, (char *) "u_achieve", sizeof(struct u_achieve)}, */ + { NHTYPE_COMPLEX, (char *) "u_conduct", sizeof(struct u_conduct) }, + { NHTYPE_COMPLEX, (char *) "u_event", sizeof(struct u_event) }, + { NHTYPE_COMPLEX, (char *) "u_have", sizeof(struct u_have) }, + { NHTYPE_COMPLEX, (char *) "u_realtime", sizeof(struct u_realtime) }, + { NHTYPE_COMPLEX, (char *) "u_roleplay", sizeof(struct u_roleplay) }, + { NHTYPE_COMPLEX, (char *) "version_info", sizeof(struct version_info) }, + { NHTYPE_COMPLEX, (char *) "vlaunchinfo", sizeof(union vlaunchinfo) }, + { NHTYPE_COMPLEX, (char *) "vptrs", sizeof(union vptrs) }, + { NHTYPE_COMPLEX, (char *) "you", sizeof(struct you) } + +}; + + +/* + * These have arrays of other structs, not just arrays of + * simple types. We need to put array handling right into + * the code for these ones. + */ +struct needs_array_handling nah[] = { + {"fakecorr", (char *) "egd"}, + {"bill", "eshk"}, + {"msrooms", "mapseen"}, + {"mtrack", "monst"}, + {"ualignbase", "you"}, + {"weapon_skills", "you"}, +}; + +/* conditional code tags - eecch */ +const char *condtag[] = { +#ifdef SYSFLAGS + "sysflag","altmeta","#ifdef AMIFLUSH", "", + "sysflag","amiflush","","#endif /*AMIFLUSH*/", + "sysflag","numcols", "#ifdef AMII_GRAPHICS", "", + "sysflag","amii_dripens","","", + "sysflag","amii_curmap","","#endif", + "sysflag","fast_map", "#ifdef OPT_DISMAP", "#endif", + "sysflag","asksavedisk","#ifdef MFLOPPY","#endif", + "sysflag","page_wait", "#ifdef MAC", "#endif", +#endif + "linfo","where","#ifdef MFLOPPY","", + "linfo","time","","", + "linfo","size","","#endif /*MFLOPPY*/", + "obj","oinvis","#ifdef INVISIBLE_OBJECTS", "#endif", + (char *)0,(char *)0,(char *)0, (char *)0 +}; + +DISABLE_WARNING_UNREACHABLE_CODE + +int main(int argc, char *argv[]) +{ + tagcount = 0; + + if (argc > 1) infilenm = argv[1]; + if (!infilenm || !*infilenm) infilenm = DEFAULTTAGNAME; + + infile = fopen(infilenm,"r"); + if (!infile) { + printf("%s not found or unavailable\n",infilenm); + quit(); + } else { + while (fgets(line, sizeof line, infile)) { + ++lineno; + /* if (lineno == 868) DebugBreak(); */ + doline(line); + } + + fclose(infile); + printf("\nRead in %ld lines and stored %d tags in memory.\n", lineno, + tagcount); +#if 0 + showthem(); +#endif + generate_c_files(); + printf("Created %s\n", SFDATA_NAME); + printf("Created %s\n", SFPROTO_NAME); + exit(EXIT_SUCCESS); + /*NOTREACHED*/ + return 0; + } +} + +RESTORE_WARNINGS + +static void doline(char *aline) +{ + char buf[255]; + struct tagstruct *tmptag; + + if (!aline || (aline && *aline == '!')) { + return; + } + tmptag = malloc(sizeof(struct tagstruct)); + + if (!tmptag) { + out_of_memory(); + } + assert(tmptag != 0); + *tmptag = zerotag; + tmptag->marker = 0xDEADBEEF; + + strncpy(buf, deeol(aline), sizeof buf - 1); + taglineparse(buf, tmptag); + chain(tmptag); + return; +} + +static struct tagstruct *prevtag = (struct tagstruct *) 0; + +static void chain(struct tagstruct *tag) +{ + + if (!first) { + tag->next = (struct tagstruct *)0; + first = tag; + } else { + tag->next = (struct tagstruct *)0; + if (prevtag) { + if (prevtag->marker == 0xDEADBEEF) { + prevtag->next = tag; + } else { + printf("Possible corruption."); + quit(); + } + } else { + printf("Error - No previous tag at %s\n", tag->tag); + } + } + prevtag = tag; + ++tagcount; +} +static void quit(void) +{ + exit(EXIT_FAILURE); +} + +static void out_of_memory(void) +{ + printf("maketags: out of memory at line %ld of %s\n", + lineno, infilenm); + quit(); +} + +#if 0 +static char empt[] = {0, 0, 0, 0, 0, 0, 0, 0}; +#endif + +#if 0 +static char *member_array_dims(struct tagstruct *tmptag, char *buf) +{ + if (buf && tmptag) { + if (tmptag->arraysize1[0]) + Sprintf(buf, "[%s]", tmptag->arraysize1); + if (tmptag->arraysize2[0]) + Sprintf(eos(buf), "[%s]", tmptag->arraysize2); + return buf; + } + return empt; +} + +static char *member_array_size(struct tagstruct *tmptag, char *buf) +{ + if (buf && tmptag) { + if (tmptag->arraysize1[0]) + strcpy(buf, tmptag->arraysize1); + if (tmptag->arraysize2[0]) + Sprintf(eos(buf), " * %s", tmptag->arraysize2); + return buf; + } + return empt; +} +#endif + +void set_member_array_size(struct tagstruct *tmptag) +{ + char buf[BUFSZ]; + /* static char result[49]; */ + char *arr1 = (char *)0, *arr2 = (char *)0, *tmp; + int cnt = 0; + + if (!tmptag) return; + strcpy(buf, tmptag->searchtext); + + tmptag->arraysize1[0] = '\0'; + tmptag->arraysize2[0] = '\0'; + + /* find left-open square bracket */ + tmp = strchr(buf, '['); + if (tmp) { + arr1 = tmp; + *tmp = '\0'; + --tmp; + /* backup and make sure the [] are on the right tag */ + while (!(*tmp == SPACE || *tmp == TAB || *tmp ==',' || cnt > 50)) { + --tmp; + cnt++; + } + if (cnt > 50) return; + tmp++; + if (strcmp(tmp, tmptag->tag) == 0) { + ++arr1; + tmp = strchr(arr1, ']'); + if (tmp) { + arr2 = tmp; + ++arr2; + *tmp = '\0'; + if (*arr2 == '[') { /* two-dimensional array */ + ++arr2; + tmp = strchr(arr2, ']'); + if (tmp) *tmp = '\0'; + } else { + arr2 = (char *)0; + } + } + } else { + arr1 = (char *)0; + } + } + if (arr1) (void)strcpy(tmptag->arraysize1, arr1); + if (arr2) (void)strcpy(tmptag->arraysize2, arr2); +} + +static void parseExtensionFields (struct tagstruct *tmptag, char *buf) +{ + char *p = buf; + while (p != (char *)0 && *p != '\0') { + while (*p == TAB) + *p++ = '\0'; + if (*p != '\0') { + char *colon; + char *field = p; + + p = strchr (p, TAB); + if (p != (char *)0) + *p++ = '\0'; + colon = strchr (field, ':'); + if (colon == (char *)0) { + tmptag->tagtype = *field; + } else { + const char *key = field; + const char *value = colon + 1; + *colon = '\0'; + if ((strcmp (key, "struct") == 0) || + (strcmp (key, "union") == 0)) { + colon = strstr(value,"::"); + if (colon) + value = colon +2; + strcpy(tmptag->parenttype, key); + strcpy(tmptag->parent, value); + } + } + } + } +} + +void +taglineparse(char *p, struct tagstruct *tmptag) +{ + int fieldsPresent = 0; + char *pattern = 0, *tmp1 = 0; + int linenumber = 0; + char *tab = strchr (p, TAB); + + if (tab != NULL) { + *tab = '\0'; + strcpy(tmptag->tag,p); + p = tab + 1; + tab = strchr (p, TAB); + if (tab != NULL) { + *tab = '\0'; + p = tab + 1; + if (*p == '/' || *p == '?') { + /* parse pattern */ + int delimiter = *(unsigned char *) p; + linenumber = 0; + pattern = p; + do { + p = strchr (p + 1, delimiter); + } while (p != (char *)0 && *(p - 1) == '\\'); + + if (p == (char *)0) { + /* invalid pattern */ + } else + ++p; + } else if (isdigit ((int) *(unsigned char *) p)) { + /* parse line number */ + pattern = p; + linenumber = atol(p); + while (isdigit((int) *(unsigned char *) p)) + ++p; + } else { + /* invalid pattern */ + } + fieldsPresent = (strncmp (p, ";\"", 2) == 0); + *p = '\0'; + + if (fieldsPresent) + parseExtensionFields (tmptag, p + 2); + } + } + assert(pattern != NULL); + + strcpy(tmptag->searchtext, pattern); + tmptag->linenum = linenumber; + + /* add the array dimensions */ + set_member_array_size(tmptag); + + /* determine if this is a pointer and mark it as such */ + if (tmptag->searchtext[0] && + (tmptag->tagtype == 'm' || tmptag->tagtype == 's')) { + char ptrbuf[BUFSZ], searchbuf[BUFSZ]; + + (void) strcpy(ptrbuf, tmptag->searchtext); + Sprintf(searchbuf,"*%s", tmptag->tag); + tmp1 = strstr(ptrbuf, searchbuf); + if (!tmp1) { + Sprintf(searchbuf,"* %s", tmptag->tag); + tmp1 = strstr(ptrbuf, searchbuf); + } + if (tmp1) { + while ((tmp1 > ptrbuf) && (*tmp1 != SPACE) && + (*tmp1 != TAB) && (*tmp1 != ',')) + tmp1--; + tmp1++; + while (*tmp1 == '*') + tmp1++; + *tmp1 = '\0'; + /* now find the first * before this in case multiple things + are declared on this line */ + tmp1 = strchr(ptrbuf+2, '*'); + if (tmp1) { + tmp1++; + *tmp1 = '\0'; + tmp1 = ptrbuf + 2; + while (*tmp1 == SPACE || *tmp1 == TAB || *tmp1 == ',') + ++tmp1; + (void)strcpy(tmptag->ptr, tmp1); + } + } + } +} + +/* eos() is copied from hacklib.c */ +/* return the end of a string (pointing at '\0') */ +char * +eos(char *s) +{ + while (*s) s++; /* s += strlen(s); */ + return s; +} + +static char stripbuf[255]; + +#if 0 +static char *stripspecial(char *st) +{ + char *out = stripbuf; + *out = '\0'; + if (!st) return st; + while(*st) { + if (*st >= SPACE) + *out++ = *st++; + else + st++; + } + *out = '\0'; + return stripbuf; +} +#endif + +static char *deblank(char *st) +{ + char *out = stripbuf; + *out = '\0'; + if (!st) return st; + while(*st) { + if (*st == SPACE) { + *out++ = '_'; + st++; + } else + *out++ = *st++; + } + *out = '\0'; + return stripbuf; +} + +static char *deeol(char *st) +{ + char *out = stripbuf; + *out = '\0'; + if (!st) return st; + while(*st) { + if ((*st == '\r') || (*st == '\n')) { + st++; + } else + *out++ = *st++; + } + *out = '\0'; + return stripbuf; +} + +#if 0 +static void showthem(void) +{ + char buf[BUFSZ], *tmp; + struct tagstruct *t = first; + while(t) { + printf("%-28s %c, %-16s %-10s", t->tag, t->tagtype, + t->parent, t->parenttype); +#if 0 + t->parent[0] ? t->searchtext : ""); +#endif + buf[0] = '\0'; + tmp = member_array_dims(t,buf); + if (tmp) printf("%s", tmp); + printf("%s","\n"); + t = t->next; + } +} +#endif + +#if 0 +static boolean +is_prim(char *sdt) +{ + int k = 0; + if (sdt) { + /* special case where we don't match entire thing */ + if (!strncmpi(sdt, "Bitfield",8)) + return TRUE; + for (k = 0; k < SIZE(readtagstypes); ++k) { + if (!strcmpi(readtagstypes[k].dtype, sdt)) { + if (readtagstypes[k].dtclass == NHTYPE_SIMPLE) + return TRUE; + else + return FALSE; + } + } + } + return FALSE; +} +#endif + +char * +findtype(char *st, char *tag) +{ + static char ftbuf[512]; + static char prevbuf[512]; + char *tmp1, *tmp2, *tmp3, *tmp4; + const char *r; + + if (!st) return (char *)0; + + if (st && strstr(st, "mapseen")) { + int xx = 0; + + xx++; + } + if (st[0] == '/' && st[1] == '^') { + tmp2 = tmp3 = tmp4 = (char *)0; + tmp1 = &st[3]; + while (*tmp1) { + if (isspace(*tmp1)) + ; /* skip it */ + else + break; + ++tmp1; + } + if (!strncmp(tmp1, tag, strlen(tag))) { + if(strlen(tag) == 1) { + char *sc = tmp1; + /* Kludge: single char match is too iffy, + check to make sure its a complete + token that we're comparing to. */ + ++sc; + if (!(*sc == '_' || (*sc > 'a' && *sc < 'z') || + (*sc > 'A' && *sc < 'Z') || (*sc > '0' && *sc < '9'))) + return (char *)0; + } else { + return (char *)0; + } + } + if (*tmp1) { + if (!strncmp(tmp1, "Bitfield", 8)) { + strcpy(ftbuf, tmp1); + tmp1 = ftbuf; + tmp3 = strchr(tmp1, ')'); + if (tmp3) { + tmp3++; + *tmp3 = '\0'; + return ftbuf; + } + return (char *)0; + } + } + if (*tmp1) { + int prevchar = 0; + strcpy(ftbuf, tmp1); + tmp1 = ftbuf; + /* find space separating first word with second */ + while (!isspace(*tmp1)) { + prevchar = *tmp1; + ++tmp1; + } + + prevchar = 0; + /* some oddball cases */ + if (prevchar == ',' || prevchar == ';') { + tmp3 = strchr(ftbuf, ','); + tmp2 = strstr(ftbuf, tag); + return prevbuf; + } else { + int chkcnt = 0; + + /* a comma means that more than one thing declared on ine */ + tmp3 = strchr(tmp1, ','); + while (chkcnt < 3 && (tmp2 = strstr(tmp1, tag)) + && (prevchar = *(tmp2 - 1)) + && ((prevchar == '_') + || (prevchar >= 'a' && prevchar <= 'z') + || (prevchar >= 'A' && prevchar <= 'Z') + || (prevchar >= '0' && prevchar <= '9'))) { + tmp1 = tmp2 + 1; + chkcnt++; + } + } + /* make sure we're matching a complete token */ + if (tmp2) { + tmp4 = tmp2 + strlen(tag); + if ((*tmp4 == '_') || (*tmp4 >= 'a' && *tmp4 <= 'z') || + (*tmp4 >= 'A' && *tmp4 <= 'Z') || (*tmp4 >= '0' && *tmp4 <= '9')) + /* jump to next occurence then */ + tmp2 = strstr(tmp4, tag); + } + /* tag w/o comma OR tag found w comma and tag before comma */ + if ((tmp2 && !tmp3) || ((tmp2 && tmp3) && (tmp2 < tmp3))) { + *tmp2 = '\0'; + --tmp2; + while (isspace(*tmp2)) + --tmp2; + tmp2++; + *tmp2 = '\0'; + } + /* comma and no tag OR tag w comma and comma before tag */ + else if ((tmp3 && !tmp2) || ((tmp2 && tmp3) && (tmp3 < tmp2))) { + --tmp3; + if (isspace(*tmp3)) { + while (isspace(*tmp3)) + --tmp3; + } + while (!isspace(*tmp3) && (*tmp3 != '*')) + --tmp3; + while (isspace(*tmp3)) + --tmp3; + tmp3++; + *tmp3 = '\0'; + } + /* comma or semicolon immediately following tag */ + else { + volatile int y = 0; + nhUse(y); + y = 1; + } + if (strncmpi(ftbuf, "struct ", 7) == 0) + r = (const char *) (ftbuf + 7); + else if (strncmpi(ftbuf, "union ", 6) == 0) + r = (const char *) (ftbuf + 6); + /* a couple of kludges follow unfortunately */ + else if (strncmpi(ftbuf, "coord", 5) == 0 + && strncmpi(ftbuf, "coordxy", 7) != 0) + r = "nhcoord"; + else if (strncmpi(ftbuf, "anything", 8) == 0) + r = "any"; + else if (strncmpi(ftbuf, "const char", 10) == 0) + r = "char"; + else + r = (const char *) ftbuf; + strcpy(prevbuf, r); + return prevbuf; + } + } + prevbuf[0] = '\0'; + return (char *)0; +} + +int current_type = 64, gotit = 0; + +boolean +listed(struct tagstruct *t) +{ + int k; + + if ((strncmpi(t->tag, "Bitfield", 8) == 0) || + (strcmpi(t->tag, "string") == 0)) + return TRUE; + for (k = 0; k < SIZE(readtagstypes); ++k) { + if (k == current_type) + gotit = k; + /* This needs to be case-sensitive to avoid generating collision + * between 'align' and 'Align'. + */ + if (strcmp(readtagstypes[k].dtype, t->tag) == 0) + return TRUE; + } + return FALSE; +} + +/* TIME_type: type of the argument to time(); we actually use &(time_t) */ +#if defined(BSD) && !defined(POSIX_TYPES) +#define TIME_type long * +#else +#define TIME_type time_t * +#endif +/* LOCALTIME_type: type of the argument to localtime() */ +#if (defined(ULTRIX) && !(defined(ULTRIX_PROTO) || defined(NHSTDC))) \ + || (defined(BSD) && !defined(POSIX_TYPES)) +#define LOCALTIME_type long * +#else +#define LOCALTIME_type time_t * +#endif + +const char *preamble[] = { + "/* Copyright (c) NetHack Development Team %d. */\n", + "/* NetHack may be freely redistributed. See license for details. */\n\n", + "/* THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE! */\n\n", + "#include \"hack.h\"\n", + "#include \"artifact.h\"\n", + "#include \"func_tab.h\"\n", + "#include \"integer.h\"\n", + "#include \"wintype.h\"\n", + (char *)0 +}; +char crbuf[BUFSZ]; + +DISABLE_WARNING_FORMAT_NONLITERAL + +static const char *get_preamble(int n) +{ + const char *r = preamble[n]; + + if (!n) { + time_t datetime = 0; + struct tm *lt; + + (void) time((TIME_type) &datetime); + lt = localtime((LOCALTIME_type) &datetime); + Sprintf(crbuf, preamble[0], (1900 + lt->tm_year)); + r = crbuf; + } + return r; +} + +RESTORE_WARNING_FORMAT_NONLITERAL + +static void output_types(FILE *fp1) +{ + int k, cnt /*, hcnt = 1 */; + struct tagstruct *t = first; + + Fprintf(fp1, "%s", + "struct nhdatatypes_t nhdatatypes[] = {\n"); + + for (k = 0; k < SIZE(readtagstypes); ++k) { + if (readtagstypes[k].dtclass == NHTYPE_SIMPLE) { + Fprintf(fp1,"\t{NHTYPE_SIMPLE, (char *) \"%s\", sizeof(%s)},\n", + readtagstypes[k].dtype, + (strncmpi(readtagstypes[k].dtype, "Bitfield", 8) == 0) ? + "uint8_t" : + (strcmpi(readtagstypes[k].dtype, "string") == 0) ? + "uchar" : + (strcmpi(readtagstypes[k].dtype, "any") == 0) ? + "anything" : readtagstypes[k].dtype); +/* dtmacro(readtagstypes[k].dtype,0)); */ +#if 0 + Fprintf(fp2, "#define %s\t%s%d\n", dtmacro(readtagstypes[k].dtype,1), + (strlen(readtagstypes[k].dtype) > 12) ? "" : + (strlen(readtagstypes[k].dtype) < 5) ? "\t\t" : + "\t", hcnt++); +#endif + } + } + cnt = 0; + while(t) { + if (listed(t) && ((t->tagtype == 's') || (t->tagtype == 'u'))) { + if (!strcmp(t->tag, "any")) { + t = t->next; + continue; + } + if (cnt > 0) + Fprintf(fp1, "%s", ",\n"); + Fprintf(fp1, "\t{NHTYPE_COMPLEX, (char *) \"%s\", sizeof(%s %s)}", + t->tag, + (t->tagtype == 's') ? "struct" : "union", t->tag); + cnt += 1; + } + t = t->next; + } + Fprintf(fp1, "%s", "\n};\n\n"); + Fprintf(fp1, "int nhdatatypes_size(void)\n{\n\treturn SIZE(nhdatatypes);\n}\n\n"); +} + +static void generate_c_files(void) +{ + struct tagstruct *t = first; +#ifdef KR1ED + long clocktim = 0; +#else + time_t clocktim = 0; +#endif + char *c, cbuf[60], sfparent[BUFSZ], funcnam[2][BUFSZ], *substruct, *gline, + norm_param_buf[BUFSZ]; + FILE *SFO_DATA, *SFI_DATA, *SFDATATMP, *SFO_PROTO, *SFI_PROTO, + *SFDATA, *SFPROTO, *SF_NORMALIZE_POINTERS; + int k = 0, j /*, opening, , closetag = 0 */; + const char *pt; + /* char *layout; */ + char *ft, *last_ft = (char *)0; + int okeydokey, x, a; + boolean did_i; + boolean normalize_param_used; + + SFDATA = fopen(SFDATA_NAME, "w"); + if (!SFDATA) return; + + SFPROTO = fopen(SFPROTO_NAME, "w"); + if (!SFPROTO) return; + + SFO_DATA = fopen("../util/sfo_data.tmp", "w"); + if (!SFO_DATA) return; + + SFO_PROTO = fopen("../include/sfo_proto.tmp", "w"); + if (!SFO_PROTO) return; + + SFI_PROTO = fopen("../include/sfi_proto.tmp", "w"); + if (!SFI_PROTO) return; + + SFI_DATA = fopen("../util/sfi_data.tmp", "w"); + if (!SFI_DATA) return; + + SFDATATMP = fopen("../util/sfdata.tmp", "w"); + if (!SFDATATMP) return; + + SF_NORMALIZE_POINTERS = fopen("../util/sfnormptrs.tmp", "w"); + if (!SF_NORMALIZE_POINTERS) return; + + (void) time(&clocktim); + Strcpy(cbuf, ctime(&clocktim)); + + for (c = cbuf; *c; c++) + if (*c == '\n') + break; + *c = '\0'; /* strip off the '\n' */ + + /* begin sfproto.h */ + Fprintf(SFPROTO,"/* NetHack %d.%d sfproto.h */\n", + VERSION_MAJOR, VERSION_MINOR); + for (j = 0; j < 3; ++j) + Fprintf(SFPROTO, "%s", get_preamble(j)); + Fprintf(SFPROTO, "#ifndef SFPROTO_H\n#define SFPROTO_H\n\n"); + Fprintf(SFPROTO, "#include \"hack.h\"\n#include \"integer.h\"\n#include \"wintype.h\"\n\n"); + + Fprintf(SFPROTO,"%s\n", "extern int critical_members_count(void);"); + Fprintf(SFPROTO,"%s\n", "extern void sfo_bitfield(NHFILE *, uint8_t *, const char *, int);"); + Fprintf(SFPROTO,"%s\n", "extern void sfi_bitfield(NHFILE *, uint8_t *, const char *, int);"); + Fprintf(SFO_PROTO, "/* generated output functions */\n"); + Fprintf(SFI_PROTO, "/* generated input functions */\n"); + + /* begin sfdata.c */ + Fprintf(SFDATA,"/* NetHack %d.%d sfdata.c */\n", + VERSION_MAJOR, VERSION_MINOR); + for (j = 0; preamble[j]; ++j) + Fprintf(SFDATA, "%s", get_preamble(j)); + Fprintf(SFDATA, "#include \"sfprocs.h\"\n"); + Fprintf(SFDATA, "#include \"sfproto.h\"\n\n"); + Fprintf(SFDATA, "#define NHTYPE_SIMPLE 1\n"); + Fprintf(SFDATA, "#define NHTYPE_COMPLEX 2\n\n"); + Fprintf(SFDATA, "struct nhdatatypes_t {\n"); + Fprintf(SFDATA, " uint dtclass;\n"); + Fprintf(SFDATA, " char *dtype;\n"); + Fprintf(SFDATA, " size_t dtsize;\n};\n\n"); + Fprintf(SFDATA,"static uint8_t bitfield = 0;\n"); + + /* begin sfnormptrs.tmp */ + Fprintf(SF_NORMALIZE_POINTERS, + "void normalize_pointers_any(union any *d_any);\n\n"); + Fprintf(SF_NORMALIZE_POINTERS, + "void\n" + "normalize_pointers_any(union any *d_any UNUSED)\n" + "{\n" + "}\n"); + + output_types(SFDATATMP); + Fprintf(SFDATATMP, "const char *critical_members[] = {\n"); + + k = 0; + did_i = FALSE; + while(k < SIZE(readtagstypes)) { + boolean insert_const = FALSE; + suppress_count = TRUE; + + if (readtagstypes[k].dtclass == NHTYPE_COMPLEX) { + + if (!strncmpi(readtagstypes[k].dtype,"Bitfield",8)) { + Fprintf(SFO_DATA, + "\nvoid\nsfo_bitfield(nhfp,\n" + "NHFILE *nhfp,\n" + "uint8_t *d_bitfield,\n" + "const char *myname\n" + "int bflen)\n" + "{\n"); + + Fprintf(SFI_DATA, + "\nvoid\nsfi_bitfield(\n" + "NHFILE *nhfp,\n" + "uint8_t *d_bitfield,\n" + "const char *myname\n" + "int bflen)\n" + "{\n"); + } + + +#if 0 + if (!strncmpi(readtagstypes[k].dtype,"version_info",8)) + insert_const = TRUE; +#endif + + pt = (const char *) 0; + t = first; + while(t) { + if (t->tagtype == 'u' && !strcmp(t->tag, readtagstypes[k].dtype)) { + pt = "union"; + break; + } + t = t->next; + } + + if (!pt) { + pt = "struct"; + } + + (void) snprintf(funcnam[0], sizeof funcnam[0], "sfo_x_%s", readtagstypes[k].dtype); + Fprintf(SFO_PROTO, + "extern void %s(NHFILE *, %s%s %s *, const char *);\n", + fn(funcnam[0]), + insert_const ? "const " : "", + pt, readtagstypes[k].dtype); + + Fprintf(SFO_DATA, + "\nvoid\n%s(\n" + "NHFILE *nhfp,\n" + "%s%s %s *d_%s,\n" + "const char *myname)\n" + "{\n", + fn(funcnam[0]), +/* deblank(readtagstypes[k].dtype), */ + insert_const ? "const " : "", + pt, readtagstypes[k].dtype, + deblank(readtagstypes[k].dtype)); + +#if 0 + Fprintf(SFO_DATA, + " const char *parent = \"%s\";\n", + readtagstypes[k].dtype); +#endif + + (void) snprintf(funcnam[0], sizeof funcnam[0], "sfi_x_%s", + readtagstypes[k].dtype); + Fprintf(SFI_PROTO, + "extern void %s(NHFILE *, %s%s %s *, const char *);\n", + fn(funcnam[0]), + insert_const ? "const " : "", + pt, readtagstypes[k].dtype); + + Fprintf(SFI_DATA, + "\nvoid\n%s(\n" + "NHFILE *nhfp,\n" + "%s%s %s *d_%s,\n" + "const char *myname)\n" + "{\n", + fn(funcnam[0]), +/* deblank(readtagstypes[k].dtype), */ + insert_const ? "const " : "", + pt, readtagstypes[k].dtype, + deblank(readtagstypes[k].dtype)); + +#if 0 + Fprintf(SFI_DATA, + " const char *parent = \"%s\";\n", + readtagstypes[k].dtype); +#endif + + Sprintf(sfparent, "%s %s", pt, readtagstypes[k].dtype); + + + Fprintf(SF_NORMALIZE_POINTERS, + "\nvoid normalize_pointers_%s(%s " + "*d_%s);\n", + readtagstypes[k].dtype, sfparent, readtagstypes[k].dtype); + Fprintf(SF_NORMALIZE_POINTERS, + "\nvoid\nnormalize_pointers_%s(%s " + "*d_%s)\n{\n", + readtagstypes[k].dtype, sfparent, readtagstypes[k].dtype); + Snprintf(norm_param_buf, sizeof norm_param_buf, "d_%s", + readtagstypes[k].dtype); + + for (a = 0; a < SIZE(nah); ++a) { + if (!strcmp(nah[a].parent, readtagstypes[k].dtype)) { + if (!did_i) { + Fprintf(SFO_DATA, " int i;\n"); + Fprintf(SFI_DATA, " int i;\n"); + did_i = TRUE; + } + } + } + + Fprintf(SFO_DATA, "\n"); + Fprintf(SFI_DATA, "\n"); + + Fprintf(SFO_DATA, " nhUse(myname);\n"); + Fprintf(SFI_DATA, " nhUse(myname);\n"); + Fprintf(SFO_DATA, "\n"); + Fprintf(SFI_DATA, "\n"); + + /******************************************************** + * cycle through all the tags and find every tag with * + * a parent matching readtagstypes[k].dtype * + ********************************************************/ + + t = first; + normalize_param_used = FALSE; + + while(t) { + x = 0; + okeydokey = 0; +/* + if (!strcmp(t->tag, "nextc") + && !strcmp(readtagstypes[k].dtype, "engrave_info")) + __debugbreak(); +*/ + if (t->tagtype == 's') { + char *ss = strstr(t->searchtext,"{$/"); + + if (ss) { + strcpy(ssdef, t->tag); + } + t = t->next; + continue; + } + + /************insert opening conditional if needed ********/ + while(condtag[x]) { + if (!strcmp(condtag[x],readtagstypes[k].dtype) && + !strcmp(condtag[x+1],t->tag)) { + okeydokey = 1; + break; + } + x = x + 4; + } + + /* some structs are entirely defined within another struct declaration. + * Legal, but a greater challenge for us here. + */ + substruct = strstr(t->parent, "::"); + if (substruct) { + substruct += 2; + } + + if ((strcmp(readtagstypes[k].dtype, t->parent) == 0) || + (substruct && strcmp(readtagstypes[k].dtype, substruct) == 0)) { + ft = (char *)0; + + if (t->ptr[0] != '\0') + ft = &t->ptr[0]; + else + ft = findtype(t->searchtext, t->tag); + + if (ft) { + last_ft = ft; + if (okeydokey && condtag[x+2] && strlen(condtag[x+2]) > 0) { + Fprintf(SFO_DATA,"%s\n", condtag[x+2]); + Fprintf(SFI_DATA,"%s\n", condtag[x+2]); + Fprintf(SFDATATMP,"%s\n", condtag[x+2]); + } + } else { + /* use the last found one as last resort then */ + ft = last_ft; + } + + /***************** Bitfield *******************/ + if (!strncmpi(ft, "Bitfield", 8)) { + char lbuf[BUFSZ]; + int j2, z; + + Sprintf(lbuf, + " " + "bitfield = d_%s->%s;", + readtagstypes[k].dtype, t->tag); + z = (int) strlen(lbuf); + for (j2 = 0; j2 < (65 - z); ++j2) + Strcat(lbuf, " "); + Sprintf(eos(lbuf), "/* (%s) */\n", ft); + Fprintf(SFO_DATA, "%s", lbuf); + Fprintf(SFO_DATA, + " " + "sfo_bitfield(nhfp, &bitfield, \"%s\", %s);\n", + t->tag, bfsize(ft)); +#if 0 + Fprintf(SFI_DATA, + " " + "bitfield = 0;\n"); +#else + Fprintf(SFI_DATA, + " " + "bitfield = d_%s->%s; /* set it to current value for testing */\n", + readtagstypes[k].dtype, t->tag); +#endif + Fprintf(SFI_DATA, + " " + "sfi_bitfield(nhfp, &bitfield, \"%s\", %s);\n", + t->tag, bfsize(ft)); + + Fprintf(SFI_DATA, + " " + "d_%s->%s = bitfield;\n\n", + readtagstypes[k].dtype, t->tag); + Fprintf(SFDATATMP, + "\t\"%s:%s:%s\",\n", + sfparent, t->tag, ft); + } else { + /**************** not a bitfield ****************/ + char arrbuf[BUFSZ]; + char lbuf[BUFSZ * 2]; /* sprintf target for others, gcc + complaint */ + char fnbuf[BUFSZ]; + char altbuf[BUFSZ]; + boolean isptr = FALSE, kludge_sbrooms = FALSE, array_of_ptrs = FALSE; + boolean insert_loop = FALSE; + int j2, z; + + altbuf[0] = '\0'; + /*************** kludge for sbrooms *************/ + if (!strcmp(t->tag, "sbrooms")) { + kludge_sbrooms = TRUE; + (void) strcpy(t->arraysize1, "MAX_SUBROOMS"); + insert_loop = TRUE; + array_of_ptrs = TRUE; + } + if (!strcmp(t->parent, "engr") + && !strcmp(t->tag, "engr_txt")) { + (void) strcpy(t->arraysize1, "text_states"); + insert_loop = TRUE; + array_of_ptrs = TRUE; + } + if (t->arraysize2[0]) { + Sprintf(arrbuf, "(%s * %s)", t->arraysize1, + t->arraysize2); + isptr = TRUE; /* suppress the & in function args */ + } else if (t->arraysize1[0]) { + Sprintf(arrbuf, "%s", t->arraysize1); + isptr = TRUE; /* suppress the & in function args */ + } else { + Strcpy(arrbuf, "1"); + } + Strcpy(fnbuf, dtfn(ft, 0, &isptr)); + /* + * determine if this is one of the special cases + * where there's an array of structs instead of + * an array of simple types. We need to insert + * a for loop in those cases. + */ + for (a = 0; a < SIZE(nah); ++a) { + if (!strcmp(nah[a].parent, t->parent)) + if (!strcmp(nah[a].nm, t->tag)) + insert_loop = TRUE; + } + if (isptr && !strcmp(fnbuf, readtagstypes[k].dtype)) { + Strcpy(altbuf, "genericptr"); + } else if (isptr + && (!strcmp(t->ptr, "struct permonst *") + || !strcmp(t->ptr, "struct monst *") + || !strcmp(t->ptr, "struct obj *") + || !strcmp(t->ptr, "struct cemetery *") + || !strcmp(t->ptr, "struct container *") + || !strcmp(t->ptr, "struct mextra *") + || !strcmp(t->ptr, "struct oextra *") + || !strcmp(t->ptr, "struct s_level *") + || !strcmp(t->ptr, "struct bill_x *") + || !strcmp(t->ptr, "struct trap *") + || !strcmp(t->ptr, "struct egd *") + || !strcmp(t->ptr, "struct epri *") + || !strcmp(t->ptr, "struct eshk *") + || !strcmp(t->ptr, "struct emin *") + || !strcmp(t->ptr, "struct ebones *") + || !strcmp(t->ptr, "struct edog *"))) { + Strcpy(altbuf, "genericptr"); + } else if (isptr + && (!strcmp(t->parent, "engr") + && !strcmp(t->tag, "engr_txt"))) { + Strcpy(altbuf, "genericptr"); + } else if (isptr + && (!strcmp(t->parent, "mapseen") + && !strcmp(t->tag, "br"))) { + Strcpy(altbuf, "genericptr"); + + // } else if (isptr + // && + // (!strcmp(t->parent, + // "engrave_info") + // && + // !strcmp(t->tag, + // "nextc"))) { + // Strcpy(altbuf, + // "genericptr"); + + } else if ( + (isptr && !strcmp(t->ptr, "char *")) + && ((!strcmp(t->parent, "engrave_info") + && !strcmp(t->tag, "nextc")) + || (!strcmp(t->parent, "mapseen") + && !strcmp(t->tag, "custom")) + || (!strcmp(t->parent, "mapseen") + && !strcmp(t->tag, "custom")) + || (!strcmp(t->parent, "mextra") + && !strcmp(t->tag, "mgivenname")) + || (!strcmp(t->parent, "gamelog_line") + && !strcmp(t->tag, "text")) + || (!strcmp(t->parent, "oextra") + && !strcmp(t->tag, "oname")) + || (!strcmp(t->parent, "oextra") + && !strcmp(t->tag, "omailcmd")))) { + Strcpy(altbuf, "genericptr"); + } else if (isptr && !strcmp(t->tag, "oc_uname")) { + Strcpy(altbuf, "genericptr"); + } else { + Strcpy(altbuf, fnbuf); + } + if (isptr && (strcmp(altbuf, "genericptr") != 0) + && (t->ptr[0] != 0 + && (*(t->ptr + (strlen(t->ptr) - 1)) == '*') + && (strcmp(t->ptr, altbuf) != 0))) { + fprintf( + stderr, + "WARNING - \"%s\" in %s called \"%s\" " + "resulted in an unexpected set of inputs/outputs " + "(%s)\n", + (t->ptr[0] != 0 && strlen(t->ptr)) ? t->ptr : "unknown", + (t->parent[0] != 0 && strlen(t->parent)) ? t->parent + : "?", + (t->tag[0] != 0 && strlen(t->tag)) ? t->tag : "?", + altbuf); + } + /* kludge for attribs */ + if (!strcmp(readtagstypes[k].dtype, "attribs") + && !strcmp(arrbuf, "A_MAX")) { + insert_loop = TRUE; + } + if (insert_loop) { + Fprintf(SFO_DATA, " for (%si = 0; i < %s; ++i)\n", + did_i ? "" : "int ", arrbuf); + Fprintf(SFI_DATA, " for (%si = 0; i < %s; ++i)\n", + did_i ? "" : "int ", arrbuf); + if (array_of_ptrs) { + Fprintf(SF_NORMALIZE_POINTERS, + " for (%si = 0; i < %s; ++i)\n", + did_i ? "" : "int ", arrbuf); + } + arrbuf[0] = '1'; + arrbuf[1] = '\0'; + } + if (isptr + && (t->ptr[0] != 0 + && (*(t->ptr + (strlen(t->ptr) - 1)) == '*') + && (strcmp(t->ptr, altbuf) != 0))) { + Fprintf( + SF_NORMALIZE_POINTERS, + " %sd_%s->%s%s%s%s = d_%s->%s%s%s%s ? (%s) 1 : (%s) 0;\n", + (insert_loop && array_of_ptrs) ? " " : "", + t->parent, t->tag, + (insert_loop && array_of_ptrs) ? "[" : "", + (insert_loop && array_of_ptrs) ? "i" : "", + (insert_loop && array_of_ptrs) ? "]" : "", + t->parent, t->tag, + (insert_loop && array_of_ptrs) ? "[" : "", + (insert_loop && array_of_ptrs) ? "i" : "", + (insert_loop && array_of_ptrs) ? "]" : "", + t->ptr, + t->ptr); + normalize_param_used = TRUE; + } + Snprintf(lbuf, sizeof lbuf, + " " + "%ssfo%s_%s(nhfp, %s%sd_%s->%s%s, \"%s\"%s%s);", + insert_loop ? " " : "", + (readtagstypes[k].dtclass == NHTYPE_SIMPLE || no_x(altbuf)) ? "" + : "_x", + altbuf, + (isptr && !strcmp(altbuf, "genericptr")) + ? "(genericptr_t) " + : "", + (isptr && !insert_loop && !kludge_sbrooms + && strcmp(altbuf, "genericptr")) + ? "" + : "&", + readtagstypes[k].dtype, t->tag, + insert_loop ? "[i]" + : "", + t->tag, strcmp(altbuf, "char") != 0 ? "" : ", ", + strcmp(altbuf, "char") != 0 ? "" : arrbuf); + /* align comments */ + z = (int) strlen(lbuf); + for (j2 = 0; j2 < (65 - z); ++j2) + Strcat(lbuf, " "); + Sprintf(eos(lbuf), "/* (%s) */\n", ft); + Fprintf(SFO_DATA, "%s", lbuf); + + Snprintf( + lbuf, sizeof lbuf, + " " + "%ssfi%s_%s(nhfp, %s%sd_%s->%s%s, \"%s\"%s%s);\n", + insert_loop ? " " : "", + (readtagstypes[k].dtclass == NHTYPE_SIMPLE + || no_x(altbuf)) + ? "" + : "_x", + altbuf, + (isptr && !strcmp(altbuf, "genericptr")) + ? "(genericptr_t) " + : "", + (isptr && !insert_loop && !kludge_sbrooms + && strcmp(altbuf, "genericptr")) + ? "" + : "&", + readtagstypes[k].dtype, t->tag, + kludge_sbrooms ? "[0]" + : insert_loop ? "[i]" + : "", + t->tag, strcmp(altbuf, "char") != 0 ? "" : ", ", + strcmp(altbuf, "char") != 0 ? "" : arrbuf); + Fprintf(SFI_DATA, "%s", lbuf); + Fprintf(SFDATATMP, + "\t\"%s:%s:%s\",\n", + sfparent, t->tag,fieldfix(ft,ssdef)); + kludge_sbrooms = FALSE; + array_of_ptrs = FALSE; + altbuf[0] = '\0'; + } + + /************insert closing conditional if needed ********/ + if (okeydokey && condtag[x+3] && strlen(condtag[x+3]) > 0) { + Fprintf(SFO_DATA,"%s\n", condtag[x+3]); + Fprintf(SFI_DATA,"%s\n", condtag[x+3]); + Fprintf(SFDATATMP,"%s\n", condtag[x+3]); + } + } + t = t->next; + } + + Fprintf(SFO_DATA, "\n"); + Fprintf(SFI_DATA, "\n"); + + Fprintf(SFO_DATA, "}\n"); + Fprintf(SFI_DATA, "}\n"); + if (!normalize_param_used) { + Fprintf(SF_NORMALIZE_POINTERS, " nhUse(%s);\n", + norm_param_buf); + } + Fprintf(SF_NORMALIZE_POINTERS, "}\n"); + } + ++k; + did_i = FALSE; + } + + Fprintf(SFDATATMP,"};\n\n"); + Fprintf(SFDATATMP, "int critical_members_count(void)\n{\n\treturn SIZE(critical_members);\n}\n\n"); + + fclose(SFO_DATA); + fclose(SFI_DATA); + fclose(SFO_PROTO); + fclose(SFI_PROTO); + fclose(SFDATATMP); + fclose(SF_NORMALIZE_POINTERS); + + /* Consolidate SFO_* and SFI_* etc into single files */ + + SFO_DATA = fopen("../util/sfo_data.tmp", "r"); + if (!SFO_DATA) return; + while ((gline = fgetline(SFO_DATA)) != 0) { + (void) fputs(gline, SFDATA); + free(gline); + } + (void) fclose(SFO_DATA); + (void) remove("../util/sfo_data.tmp"); + + SFI_DATA = fopen("../util/sfi_data.tmp", "r"); + if (!SFI_DATA) return; + while ((gline = fgetline(SFI_DATA)) != 0) { + (void) fputs(gline, SFDATA); + free(gline); + } + (void) fclose(SFI_DATA); + (void) remove("../util/sfi_data.tmp"); + + SFO_PROTO = fopen("../include/sfo_proto.tmp", "r"); + if (!SFO_PROTO) return; + while ((gline = fgetline(SFO_PROTO)) != 0) { + (void) fputs(gline, SFPROTO); + free(gline); + } + (void) fclose(SFO_PROTO); + (void) remove("../include/sfo_proto.tmp"); + + SFI_PROTO = fopen("../include/sfi_proto.tmp", "r"); + if (!SFI_PROTO) return; + while ((gline = fgetline(SFI_PROTO)) != 0) { + (void) fputs(gline, SFPROTO); + free(gline); + } + (void) fclose(SFI_PROTO); + (void) remove("../include/sfi_proto.tmp"); + + SFDATATMP = fopen("../util/sfdata.tmp", "r"); + if (!SFDATATMP) return; + while ((gline = fgetline(SFDATATMP)) != 0) { + (void) fputs(gline, SFDATA); + free(gline); + } + (void) fclose(SFDATATMP); + (void) remove("../util/sfdata.tmp"); + + SF_NORMALIZE_POINTERS = fopen("../util/sfnormptrs.tmp", "r"); + if (!SF_NORMALIZE_POINTERS) + return; + while ((gline = fgetline(SF_NORMALIZE_POINTERS)) != 0) { + (void) fputs(gline, SFDATA); + free(gline); + } + (void) fclose(SF_NORMALIZE_POINTERS); + (void) remove("../util/sfnormptrs.tmp"); + + Fprintf(SFDATA, "/*sfdata.c*/\n"); + Fprintf(SFPROTO,"#endif /* SFPROTO_H */\n"); + (void) fclose(SFDATA); + (void) fclose(SFPROTO); +} + +#if 0 +static char * +dtmacro(const char *str, + int n) /* 1 = supress appending |SF_PTRMASK */ +{ + static char buf[128], buf2[128]; + char *nam, *c; + int ispointer = 0; + + if (!str) + return (char *)0; + (void)strncpy(buf, str, 127); + + c = buf; + while (*c) + c++; /* eos */ + + c--; + if (*c == '*') { + ispointer = 1; + *c = '\0'; + c--; + } + while(isspace(*c)) { + c--; + } + *(c+1) = '\0'; + c = buf; + + if (strncmpi(c, "Bitfield", 8) == 0) { + *(c+8) = '\0'; + } else if (strcmpi(c, "genericptr_t") == 0) { + ispointer = 1; + } else if (strncmpi(c, "const ", 6) == 0) { + c = buf + 6; + } else if ((strncmpi(c, "struct ", 7) == 0) || + (strncmpi(c, "struct\t", 7) == 0)) { + c = buf + 7; + } else if (strncmpi(c, "union ", 6) == 0) { + c = buf + 6; + } + + /* end of substruct within struct definition */ + if (strcmp(buf,"}") == 0 && strlen(ssdef) > 0) { + strcpy(buf,ssdef); + c = buf; + } + + for (nam = c; *c; c++) { + if (*c >= 'a' && *c <= 'z') + *c -= (char)('a' - 'A'); + else if (*c < 'A' || *c > 'Z') + *c = '_'; + } + (void)sprintf(buf2, "SF_%s%s", nam, + (ispointer && (n == 0)) ? " | SF_PTRMASK" : ""); + return buf2; +} +#endif + +static char * +dtfn(const char *str, + int n, /* 1 = supress appending |SF_PTRMASK */ + boolean *isptr) +{ + static char buf[128], buf2[128]; + const char *nam; + char *c; + int ispointer = 0; + + if (!str) + return (char *)0; + (void)strncpy(buf, str, 127); + + c = buf; + while (*c) c++; /* eos */ + + c--; + if (*c == '*') { + ispointer = 1; + *c = '\0'; + c--; + } + while(isspace(*c)) { + c--; + } + *(c+1) = '\0'; + c = buf; + + if (strncmpi(c, "Bitfield", 8) == 0) { + *(c+8) = '\0'; + } else if (strcmpi(c, "genericptr_t") == 0) { + ispointer = 1; + } else if (strncmpi(c, "const ", 6) == 0) { + c = buf + 6; + } else if ((strncmpi(c, "struct ", 7) == 0) || + (strncmpi(c, "struct\t", 7) == 0)) { + c = buf + 7; + } else if (strncmpi(c, "union ", 6) == 0) { + c = buf + 6; + } + + /* end of substruct within struct definition */ + if (strcmp(buf,"}") == 0 && strlen(ssdef) > 0) { + strcpy(buf,ssdef); + c = buf; + } + + for (nam = (const char *) c; *c; c++) { + if (*c >= 'A' && *c <= 'Z') + *c = tolower(*c); + else if (*c == ' ') + *c = '_'; + } + /* some fix-ups */ + if (!strcmp(nam, "genericptr_t")) + nam = "genericptr"; + else if (!strcmp(nam, "unsigned_int")) + nam = "uint"; + else if (!strcmp(nam, "unsigned_long")) + nam = "ulong"; + else if (!strcmp(nam, "unsigned_char")) + nam = "uchar"; + else if (!strcmp(nam, "unsigned_short")) + nam = "ushort"; + + if (ispointer && isptr && n == 0) + *isptr = TRUE; + (void)sprintf(buf2, "%s%s", nam, ""); + return buf2; +} + +static char * +fieldfix(char *f, char *ss) +{ + char *c /*, *dest = fieldfixbuf */; + + if (strcmp(f,"}") == 0 && strlen(ss) > 0 && strlen(ss) < BUFSZ - 1) { + /* (void)sprintf(fieldfixbuf,"struct %s", ss); */ + strcpy(fieldfixbuf,ss); + } else { + if (strlen(f) < BUFSZ - 1) strcpy(fieldfixbuf,f); + } + + /* converting any tabs to space */ + for (c = fieldfixbuf; *c; c++) + if (*c == TAB) *c = SPACE; + + return fieldfixbuf; +} + +static char * +bfsize(const char *str) +{ + static char buf[128]; + const char *c1; + char *c2, *subst; + + if (!str) + return (char *)0; + + /* kludge */ + subst = strstr(str, ",$/"); + if (subst != 0) { + subst++; + *subst++ = ' '; + *subst++ = '1'; + } + + c2 = buf; + c1 = str; + while (*c1) { + if (*c1 == ',') + break; + c1++; + } + + if (*c1 == ',') { + c1++; + while (*c1 && *c1 != ')') { + *c2++ = *c1++; + } + *c2 = '\0'; + } else { + return (char *)0; + } + return buf; +} + +/* Read one line from input, up to and including the next newline + * character. Returns a pointer to the heap-allocated string, or a + * null pointer if no characters were read. + */ +static char * +fgetline(FILE *fd) +{ + static const int inc = 256; + int len = inc; + char *c = malloc(len), *ret; + + for (;;) { + ret = fgets(c + len - inc, inc, fd); + if (!ret) { + free(c); + c = NULL; + break; + } else if (strchr(c, '\n')) { + /* normal case: we have a full line */ + break; + } + len += inc; + c = realloc(c, len); + } + return c; +} + +int +strncmpi(register const char *s1, register const char *s2, size_t n) +{ + register char t1, t2; + + while (n--) { + if (!*s2) + return (*s1 != 0); /* s1 >= s2 */ + else if (!*s1) + return -1; /* s1 < s2 */ + t1 = lowc(*s1++); + t2 = lowc(*s2++); + if (t1 != t2) + return (t1 > t2) ? 1 : -1; + } + return 0; /* s1 == s2 */ +} + +/* force 'c' into uppercase */ +char +highc(char c) +{ + return (char) (('a' <= c && c <= 'z') ? (c & ~040) : c); +} + +/* force 'c' into lowercase */ +char +lowc(char c) +{ + return (char) (('A' <= c && c <= 'Z') ? (c | 040) : c); +} + +DISABLE_WARNING_FORMAT_NONLITERAL + +/* + * Wrap snprintf for use in the main code. + * + * Wrap reasons: + * 1. If there are any platform issues, we have one spot to fix them - + * snprintf is a routine with a troubling history of bad implementations. + * 2. Add combersome error checking in one spot. Problems with text wrangling + * do not have to be fatal. + * 3. Gcc 9+ will issue a warning unless the return value is used. + * Annoyingly, explicitly casting to void does not remove the error. + * So, use the result - see reason #2. + */ +void +nh_snprintf(const char *func, int myline, char *str, size_t size, + const char *fmt, ...) +{ + va_list ap; + int n; + + va_start(ap, fmt); +#ifdef NO_VSNPRINTF + n = vsprintf(str, fmt, ap); +#else + n = vsnprintf(str, size, fmt, ap); +#endif + va_end(ap); + if (n < 0 || (size_t)n >= size) { /* is there a problem? */ + fprintf(stderr, "snprintf %s: func %s, file line %d", + n < 0 ? "format error" + : "overflow", + func, myline); + str[size-1] = 0; /* make sure it is nul terminated */ + } +} + +RESTORE_WARNING_FORMAT_NONLITERAL + +struct already_in_sfbase { + int typ; + const char *actual; + const char *replacement; +}; + +/* The ones that can't be broken down into subfields + * are NHTYPE_SIMPLE. + */ +const struct already_in_sfbase already[] = { + /* input */ + { NHTYPE_SIMPLE, "Sfi_any", "Sfi_any" }, + { NHTYPE_SIMPLE, "Sfi_boolean", "Sfi_boolean" }, + { NHTYPE_SIMPLE, "Sfi_char", "Sfi_char" }, + { NHTYPE_SIMPLE, "Sfi_coordxy", "Sfi_coordxy" }, + { NHTYPE_SIMPLE, "Sfi_int16", "Sfi_int16" }, + { NHTYPE_SIMPLE, "Sfi_int32", "Sfi_int32" }, + { NHTYPE_SIMPLE, "Sfi_long", "Sfi_long" }, + { NHTYPE_SIMPLE, "Sfi_nhcoord", "Sfi_nhcoord" }, + { NHTYPE_SIMPLE, "Sfi_schar", "Sfi_schar" }, + { NHTYPE_SIMPLE, "Sfi_uint32", "Sfi_uint32" }, + { NHTYPE_SIMPLE, "Sfi_ulong", "Sfi_ulong" }, + { NHTYPE_SIMPLE, "Sfi_xint8", "Sfi_xint8" }, + { NHTYPE_COMPLEX, "Sfi_arti_info", "Sfi_x_arti_info" }, + { NHTYPE_COMPLEX, "Sfi_branch", "Sfi_x_branch" }, + { NHTYPE_COMPLEX, "Sfi_bubble", "Sfi_x_bubble" }, + { NHTYPE_COMPLEX, "Sfi_cemetery", "Sfi_x_cemetery" }, + { NHTYPE_COMPLEX, "Sfi_context_info", "Sfi_x_context_info" }, + { NHTYPE_COMPLEX, "Sfi_d_level", "Sfi_x_d_level" }, + { NHTYPE_COMPLEX, "Sfi_damage", "Sfi_x_damage" }, + { NHTYPE_COMPLEX, "Sfi_dest_area", "Sfi_x_dest_area" }, + { NHTYPE_COMPLEX, "Sfi_dgn_topology", "Sfi_x_dgn_topology" }, + { NHTYPE_COMPLEX, "Sfi_dungeon", "Sfi_x_dungeon" }, + { NHTYPE_COMPLEX, "Sfi_ebones", "Sfi_x_ebones" }, + { NHTYPE_COMPLEX, "Sfi_edog", "Sfi_x_edog" }, + { NHTYPE_COMPLEX, "Sfi_egd", "Sfi_x_egd" }, + { NHTYPE_COMPLEX, "Sfi_emin", "Sfi_x_emin" }, + { NHTYPE_COMPLEX, "Sfi_engr", "Sfi_x_engr" }, + { NHTYPE_COMPLEX, "Sfi_epri", "Sfi_x_epri" }, + { NHTYPE_COMPLEX, "Sfi_eshk", "Sfi_x_eshk" }, + { NHTYPE_COMPLEX, "Sfi_fe", "Sfi_x_fe" }, + { NHTYPE_COMPLEX, "Sfi_flag", "Sfi_x_flag" }, + { NHTYPE_COMPLEX, "Sfi_fruit", "Sfi_x_fruit" }, + { NHTYPE_COMPLEX, "Sfi_gamelog_line", "Sfi_x_gamelog_line" }, + { NHTYPE_COMPLEX, "Sfi_kinfo", "Sfi_x_kinfo" }, + { NHTYPE_COMPLEX, "Sfi_levelflags", "Sfi_x_levelflags" }, + { NHTYPE_COMPLEX, "Sfi_linfo", "Sfi_x_linfo" }, + { NHTYPE_COMPLEX, "Sfi_ls_t", "Sfi_x_ls_t" }, + { NHTYPE_COMPLEX, "Sfi_mapseen_feat", "Sfi_x_mapseen_feat" }, + { NHTYPE_COMPLEX, "Sfi_mapseen_flags", "Sfi_x_mapseen_flags" }, + { NHTYPE_COMPLEX, "Sfi_mapseen_rooms", "Sfi_x_mapseen_rooms" }, + { NHTYPE_COMPLEX, "Sfi_mkroom", "Sfi_x_mkroom" }, + { NHTYPE_COMPLEX, "Sfi_monst", "Sfi_x_monst" }, + { NHTYPE_COMPLEX, "Sfi_mvitals", "Sfi_x_mvitals" }, + { NHTYPE_COMPLEX, "Sfi_nhrect", "Sfi_x_nhrect" }, + { NHTYPE_COMPLEX, "Sfi_obj", "Sfi_x_obj" }, + { NHTYPE_COMPLEX, "Sfi_objclass", "Sfi_x_objclass" }, + { NHTYPE_COMPLEX, "Sfi_q_score", "Sfi_x_q_score" }, + { NHTYPE_COMPLEX, "Sfi_rm", "Sfi_x_rm" }, + { NHTYPE_COMPLEX, "Sfi_s_level", "Sfi_x_s_level" }, + { NHTYPE_COMPLEX, "Sfi_spell", "Sfi_x_spell" }, + { NHTYPE_COMPLEX, "Sfi_stairway", "Sfi_x_stairway" }, + { NHTYPE_COMPLEX, "Sfi_trap", "Sfi_x_trap" }, + { NHTYPE_COMPLEX, "Sfi_version_info", "Sfi_x_version_info" }, + { NHTYPE_COMPLEX, "Sfi_you", "Sfi_x_you" }, + /* output */ + { NHTYPE_SIMPLE, "Sfo_any", "Sfo_any" }, + { NHTYPE_SIMPLE, "Sfo_boolean", "Sfo_boolean" }, + { NHTYPE_SIMPLE, "Sfo_char", "Sfo_char" }, + { NHTYPE_SIMPLE, "Sfo_coordxy", "Sfo_coordxy" }, + { NHTYPE_SIMPLE, "Sfo_int16", "Sfo_int16" }, + { NHTYPE_SIMPLE, "Sfo_int32", "Sfo_int32" }, + { NHTYPE_SIMPLE, "Sfo_long", "Sfo_long" }, + { NHTYPE_SIMPLE, "Sfo_nhcoord", "Sfo_nhcoord" }, + { NHTYPE_SIMPLE, "Sfo_schar", "Sfo_schar" }, + { NHTYPE_SIMPLE, "Sfo_uint32", "Sfo_uint32" }, + { NHTYPE_SIMPLE, "Sfo_ulong", "Sfo_ulong" }, + { NHTYPE_SIMPLE, "Sfo_xint8", "Sfo_xint8" }, + { NHTYPE_COMPLEX, "Sfo_arti_info", "Sfo_x_arti_info" }, + { NHTYPE_COMPLEX, "Sfo_branch", "Sfo_x_branch" }, + { NHTYPE_COMPLEX, "Sfo_bubble", "Sfo_x_bubble" }, + { NHTYPE_COMPLEX, "Sfo_cemetery", "Sfo_x_cemetery" }, + { NHTYPE_COMPLEX, "Sfo_context_info", "Sfo_x_context_info" }, + { NHTYPE_COMPLEX, "Sfo_d_level", "Sfo_x_d_level" }, + { NHTYPE_COMPLEX, "Sfo_damage", "Sfo_x_damage" }, + { NHTYPE_COMPLEX, "Sfo_dest_area", "Sfo_x_dest_area" }, + { NHTYPE_COMPLEX, "Sfo_dgn_topology", "Sfo_x_dgn_topology" }, + { NHTYPE_COMPLEX, "Sfo_dungeon", "Sfo_x_dungeon" }, + { NHTYPE_COMPLEX, "Sfo_ebones", "Sfo_x_ebones" }, + { NHTYPE_COMPLEX, "Sfo_edog", "Sfo_x_edog" }, + { NHTYPE_COMPLEX, "Sfo_egd", "Sfo_x_egd" }, + { NHTYPE_COMPLEX, "Sfo_emin", "Sfo_x_emin" }, + { NHTYPE_COMPLEX, "Sfo_engr", "Sfo_x_engr" }, + { NHTYPE_COMPLEX, "Sfo_epri", "Sfo_x_epri" }, + { NHTYPE_COMPLEX, "Sfo_eshk", "Sfo_x_eshk" }, + { NHTYPE_COMPLEX, "Sfo_fe", "Sfo_x_fe" }, + { NHTYPE_COMPLEX, "Sfo_flag", "Sfo_x_flag" }, + { NHTYPE_COMPLEX, "Sfo_fruit", "Sfo_x_fruit" }, + { NHTYPE_COMPLEX, "Sfo_gamelog_line", "Sfo_x_gamelog_line" }, + { NHTYPE_COMPLEX, "Sfo_kinfo", "Sfo_x_kinfo" }, + { NHTYPE_COMPLEX, "Sfo_levelflags", "Sfo_x_levelflags" }, + { NHTYPE_COMPLEX, "Sfo_linfo", "Sfo_x_linfo" }, + { NHTYPE_COMPLEX, "Sfo_ls_t", "Sfo_x_ls_t" }, + { NHTYPE_COMPLEX, "Sfo_mapseen_feat", "Sfo_x_mapseen_feat" }, + { NHTYPE_COMPLEX, "Sfo_mapseen_flags", "Sfo_x_mapseen_flags" }, + { NHTYPE_COMPLEX, "Sfo_mapseen_rooms", "Sfo_x_mapseen_rooms" }, + { NHTYPE_COMPLEX, "Sfo_mkroom", "Sfo_x_mkroom" }, + { NHTYPE_COMPLEX, "Sfo_monst", "Sfo_x_monst" }, + { NHTYPE_COMPLEX, "Sfo_mvitals", "Sfo_x_mvitals" }, + { NHTYPE_COMPLEX, "Sfo_nhrect", "Sfo_x_nhrect" }, + { NHTYPE_COMPLEX, "Sfo_obj", "Sfo_x_obj" }, + { NHTYPE_COMPLEX, "Sfo_objclass", "Sfo_x_objclass" }, + { NHTYPE_COMPLEX, "Sfo_q_score", "Sfo_x_q_score" }, + { NHTYPE_COMPLEX, "Sfo_rm", "Sfo_x_rm" }, + { NHTYPE_COMPLEX, "Sfo_s_level", "Sfo_x_s_level" }, + { NHTYPE_COMPLEX, "Sfo_spell", "Sfo_x_spell" }, + { NHTYPE_COMPLEX, "Sfo_stairway", "Sfo_x_stairway" }, + { NHTYPE_COMPLEX, "Sfo_trap", "Sfo_x_trap" }, + { NHTYPE_COMPLEX, "Sfo_version_info", "Sfo_x_version_info" }, + { NHTYPE_COMPLEX, "Sfo_you", "Sfo_x_you" }, +}; + +static const char * +fn(const char *f) +{ + int i; + + for (i = 0; i < SIZE(already); ++i) { + if (!strcmp(already[i].actual, f)) + return already[i].replacement; + } + return f; +} + +const char *force_no_x[] = { + "aligntyp", "any", "boolean", "char", "coordxy", "genericptr", + "int", "int16", "int32", "int64", "long", "schar", + "short", "size_t", "time_t", "uchar", "uint32", "uint64", + "ulong", "unsigned", "ushort", "xint16", "xint8", +}; + +static boolean +no_x(const char *s) +{ + int i; + + for (i = 0; i < SIZE(force_no_x); ++i) { + if (!strcmp(force_no_x[i], s)) + return TRUE; + } + return FALSE; +} + +struct nh_classification { + int in_sfbase; + uint dtclass; + const char *fn; + const char *replacement_fn; +}; + +struct nh_classification nhdatatypes[] = { + { 0, NHTYPE_COMPLEX, "sfi_achievement_tracking", + "sfi_achievement_tracking" }, + { 0, NHTYPE_COMPLEX, "sfi_align", "sfi_align" }, + { 0, NHTYPE_COMPLEX, "sfi_attribs", "sfi_attribs" }, + { 0, NHTYPE_COMPLEX, "sfi_bill_x", "sfi_bill_x" }, + { 0, NHTYPE_COMPLEX, "sfi_book_info", "sfi_book_info" }, + { 0, NHTYPE_COMPLEX, "sfi_branch", "sfi_branch" }, + { 0, NHTYPE_COMPLEX, "sfi_bubble", "sfi_bubble" }, + { 0, NHTYPE_COMPLEX, "sfi_cemetery", "sfi_cemetery" }, + { 0, NHTYPE_COMPLEX, "sfi_context_info", "sfi_context_info" }, + { 0, NHTYPE_COMPLEX, "sfi_d_flags", "sfi_d_flags" }, + { 0, NHTYPE_COMPLEX, "sfi_d_level", "sfi_d_level" }, + { 0, NHTYPE_COMPLEX, "sfi_damage", "sfi_damage" }, + { 0, NHTYPE_COMPLEX, "sfi_dest_area", "sfi_dest_area" }, + { 0, NHTYPE_COMPLEX, "sfi_dgn_topology", "sfi_dgn_topology" }, + { 0, NHTYPE_COMPLEX, "sfi_dig_info", "sfi_dig_info" }, + { 0, NHTYPE_COMPLEX, "sfi_dungeon", "sfi_dungeon" }, + { 0, NHTYPE_COMPLEX, "sfi_ebones", "sfi_ebones" }, + { 0, NHTYPE_COMPLEX, "sfi_edog", "sfi_edog" }, + { 0, NHTYPE_COMPLEX, "sfi_egd", "sfi_egd" }, + { 0, NHTYPE_COMPLEX, "sfi_emin", "sfi_emin" }, + { 0, NHTYPE_COMPLEX, "sfi_engr", "sfi_engr" }, + { 0, NHTYPE_COMPLEX, "sfi_engrave_info", "sfi_engrave_info" }, + { 0, NHTYPE_COMPLEX, "sfi_epri", "sfi_epri" }, + { 0, NHTYPE_COMPLEX, "sfi_eshk", "sfi_eshk" }, + { 0, NHTYPE_COMPLEX, "sfi_fakecorridor", "sfi_fakecorridor" }, + { 0, NHTYPE_COMPLEX, "sfi_fe", "sfi_fe" }, + { 0, NHTYPE_COMPLEX, "sfi_flag", "sfi_flag" }, + { 0, NHTYPE_COMPLEX, "sfi_fruit", "sfi_fruit" }, + { 0, NHTYPE_COMPLEX, "sfi_kinfo", "sfi_kinfo" }, + { 0, NHTYPE_COMPLEX, "sfi_levelflags", "sfi_levelflags" }, + { 0, NHTYPE_COMPLEX, "sfi_linfo", "sfi_linfo" }, + { 0, NHTYPE_COMPLEX, "sfi_ls_t", "sfi_ls_t" }, + { 0, NHTYPE_COMPLEX, "sfi_mapseen", "sfi_mapseen" }, + { 0, NHTYPE_COMPLEX, "sfi_mapseen_feat", "sfi_mapseen_feat" }, + { 0, NHTYPE_COMPLEX, "sfi_mapseen_flags", "sfi_mapseen_flags" }, + { 0, NHTYPE_COMPLEX, "sfi_mapseen_rooms", "sfi_mapseen_rooms" }, + { 0, NHTYPE_COMPLEX, "sfi_mextra", "sfi_mextra" }, + { 0, NHTYPE_COMPLEX, "sfi_mkroom", "sfi_mkroom" }, + { 0, NHTYPE_COMPLEX, "sfi_monst", "sfi_monst" }, + { 0, NHTYPE_COMPLEX, "sfi_mvitals", "sfi_mvitals" }, + { 0, NHTYPE_COMPLEX, "sfi_nhcoord", "sfi_nhcoord" }, + { 0, NHTYPE_COMPLEX, "sfi_nhrect", "sfi_nhrect" }, + { 0, NHTYPE_COMPLEX, "sfi_novel_tracking", "sfi_novel_tracking" }, + { 0, NHTYPE_COMPLEX, "sfi_obj", "sfi_obj" }, + { 0, NHTYPE_COMPLEX, "sfi_obj_split", "sfi_obj_split" }, + { 0, NHTYPE_COMPLEX, "sfi_objclass", "sfi_objclass" }, + { 0, NHTYPE_COMPLEX, "sfi_oextra", "sfi_oextra" }, + { 0, NHTYPE_COMPLEX, "sfi_polearm_info", "sfi_polearm_info" }, + { 0, NHTYPE_COMPLEX, "sfi_prop", "sfi_prop" }, + { 0, NHTYPE_COMPLEX, "sfi_q_score", "sfi_q_score" }, + { 0, NHTYPE_COMPLEX, "sfi_rm", "sfi_rm" }, + { 0, NHTYPE_COMPLEX, "sfi_s_level", "sfi_s_level" }, + { 0, NHTYPE_COMPLEX, "sfi_skills", "sfi_skills" }, + { 0, NHTYPE_COMPLEX, "sfi_spell", "sfi_spell" }, + { 0, NHTYPE_COMPLEX, "sfi_stairway", "sfi_stairway" }, + { 0, NHTYPE_COMPLEX, "sfi_takeoff_info", "sfi_takeoff_info" }, + { 0, NHTYPE_COMPLEX, "sfi_tin_info", "sfi_tin_info" }, + { 0, NHTYPE_COMPLEX, "sfi_trap", "sfi_trap" }, + { 0, NHTYPE_COMPLEX, "sfi_tribute_info", "sfi_tribute_info" }, + { 0, NHTYPE_COMPLEX, "sfi_u_conduct", "sfi_u_conduct" }, + { 0, NHTYPE_COMPLEX, "sfi_u_event", "sfi_u_event" }, + { 0, NHTYPE_COMPLEX, "sfi_u_have", "sfi_u_have" }, + { 0, NHTYPE_COMPLEX, "sfi_u_realtime", "sfi_u_realtime" }, + { 0, NHTYPE_COMPLEX, "sfi_u_roleplay", "sfi_u_roleplay" }, + { 0, NHTYPE_COMPLEX, "sfi_version_info", "sfi_version_info" }, + { 0, NHTYPE_COMPLEX, "sfi_victual_info", "sfi_victual_info" }, + { 0, NHTYPE_COMPLEX, "sfi_vlaunchinfo", "sfi_vlaunchinfo" }, + { 0, NHTYPE_COMPLEX, "sfi_vptrs", "sfi_vptrs" }, + { 0, NHTYPE_COMPLEX, "sfi_warntype_info", "sfi_warntype_info" }, + { 0, NHTYPE_COMPLEX, "sfi_you", "sfi_you" }, + { 0, NHTYPE_COMPLEX, "sfo_achievement_tracking", + "sfo_achievement_tracking" }, + { 0, NHTYPE_COMPLEX, "sfo_align", "sfo_align" }, + { 0, NHTYPE_COMPLEX, "sfo_attribs", "sfo_attribs" }, + { 0, NHTYPE_COMPLEX, "sfo_bill_x", "sfo_bill_x" }, + { 0, NHTYPE_COMPLEX, "sfo_book_info", "sfo_book_info" }, + { 0, NHTYPE_COMPLEX, "sfo_branch", "sfo_branch" }, + { 0, NHTYPE_COMPLEX, "sfo_bubble", "sfo_bubble" }, + { 0, NHTYPE_COMPLEX, "sfo_cemetery", "sfo_cemetery" }, + { 0, NHTYPE_COMPLEX, "sfo_context_info", "sfo_context_info" }, + { 0, NHTYPE_COMPLEX, "sfo_d_flags", "sfo_d_flags" }, + { 0, NHTYPE_COMPLEX, "sfo_d_level", "sfo_d_level" }, + { 0, NHTYPE_COMPLEX, "sfo_damage", "sfo_damage" }, + { 0, NHTYPE_COMPLEX, "sfo_dest_area", "sfo_dest_area" }, + { 0, NHTYPE_COMPLEX, "sfo_dgn_topology", "sfo_dgn_topology" }, + { 0, NHTYPE_COMPLEX, "sfo_dig_info", "sfo_dig_info" }, + { 0, NHTYPE_COMPLEX, "sfo_dungeon", "sfo_dungeon" }, + { 0, NHTYPE_COMPLEX, "sfo_ebones", "sfo_ebones" }, + { 0, NHTYPE_COMPLEX, "sfo_edog", "sfo_edog" }, + { 0, NHTYPE_COMPLEX, "sfo_egd", "sfo_egd" }, + { 0, NHTYPE_COMPLEX, "sfo_emin", "sfo_emin" }, + { 0, NHTYPE_COMPLEX, "sfo_engr", "sfo_engr" }, + { 0, NHTYPE_COMPLEX, "sfo_engrave_info", "sfo_engrave_info" }, + { 0, NHTYPE_COMPLEX, "sfo_epri", "sfo_epri" }, + { 0, NHTYPE_COMPLEX, "sfo_eshk", "sfo_eshk" }, + { 0, NHTYPE_COMPLEX, "sfo_fakecorridor", "sfo_fakecorridor" }, + { 0, NHTYPE_COMPLEX, "sfo_fe", "sfo_fe" }, + { 0, NHTYPE_COMPLEX, "sfo_flag", "sfo_flag" }, + { 0, NHTYPE_COMPLEX, "sfo_fruit", "sfo_fruit" }, + { 0, NHTYPE_COMPLEX, "sfo_kinfo", "sfo_kinfo" }, + { 0, NHTYPE_COMPLEX, "sfo_levelflags", "sfo_levelflags" }, + { 0, NHTYPE_COMPLEX, "sfo_linfo", "sfo_linfo" }, + { 0, NHTYPE_COMPLEX, "sfo_ls_t", "sfo_ls_t" }, + { 0, NHTYPE_COMPLEX, "sfo_mapseen", "sfo_mapseen" }, + { 0, NHTYPE_COMPLEX, "sfo_mapseen_feat", "sfo_mapseen_feat" }, + { 0, NHTYPE_COMPLEX, "sfo_mapseen_flags", "sfo_mapseen_flags" }, + { 0, NHTYPE_COMPLEX, "sfo_mapseen_rooms", "sfo_mapseen_rooms" }, + { 0, NHTYPE_COMPLEX, "sfo_mextra", "sfo_mextra" }, + { 0, NHTYPE_COMPLEX, "sfo_mkroom", "sfo_mkroom" }, + { 0, NHTYPE_COMPLEX, "sfo_monst", "sfo_monst" }, + { 0, NHTYPE_COMPLEX, "sfo_mvitals", "sfo_mvitals" }, + { 0, NHTYPE_COMPLEX, "sfo_nhcoord", "sfo_nhcoord" }, + { 0, NHTYPE_COMPLEX, "sfo_nhrect", "sfo_nhrect" }, + { 0, NHTYPE_COMPLEX, "sfo_novel_tracking", "sfo_novel_tracking" }, + { 0, NHTYPE_COMPLEX, "sfo_obj", "sfo_obj" }, + { 0, NHTYPE_COMPLEX, "sfo_obj_split", "sfo_obj_split" }, + { 0, NHTYPE_COMPLEX, "sfo_objclass", "sfo_objclass" }, + { 0, NHTYPE_COMPLEX, "sfo_oextra", "sfo_oextra" }, + { 0, NHTYPE_COMPLEX, "sfo_polearm_info", "sfo_polearm_info" }, + { 0, NHTYPE_COMPLEX, "sfo_prop", "sfo_prop" }, + { 0, NHTYPE_COMPLEX, "sfo_q_score", "sfo_q_score" }, + { 0, NHTYPE_COMPLEX, "sfo_rm", "sfo_rm" }, + { 0, NHTYPE_COMPLEX, "sfo_s_level", "sfo_s_level" }, + { 0, NHTYPE_COMPLEX, "sfo_skills", "sfo_skills" }, + { 0, NHTYPE_COMPLEX, "sfo_spell", "sfo_spell" }, + { 0, NHTYPE_COMPLEX, "sfo_stairway", "sfo_stairway" }, + { 0, NHTYPE_COMPLEX, "sfo_takeoff_info", "sfo_takeoff_info" }, + { 0, NHTYPE_COMPLEX, "sfo_tin_info", "sfo_tin_info" }, + { 0, NHTYPE_COMPLEX, "sfo_trap", "sfo_trap" }, + { 0, NHTYPE_COMPLEX, "sfo_tribute_info", "sfo_tribute_info" }, + { 0, NHTYPE_COMPLEX, "sfo_u_conduct", "sfo_u_conduct" }, + { 0, NHTYPE_COMPLEX, "sfo_u_event", "sfo_u_event" }, + { 0, NHTYPE_COMPLEX, "sfo_u_have", "sfo_u_have" }, + { 0, NHTYPE_COMPLEX, "sfo_u_realtime", "sfo_u_realtime" }, + { 0, NHTYPE_COMPLEX, "sfo_u_roleplay", "sfo_u_roleplay" }, + { 0, NHTYPE_COMPLEX, "sfo_version_info", "sfo_version_info" }, + { 0, NHTYPE_COMPLEX, "sfo_victual_info", "sfo_victual_info" }, + { 0, NHTYPE_COMPLEX, "sfo_vlaunchinfo", "sfo_vlaunchinfo" }, + { 0, NHTYPE_COMPLEX, "sfo_vptrs", "sfo_vptrs" }, + { 0, NHTYPE_COMPLEX, "sfo_warntype_info", "sfo_warntype_info" }, + { 0, NHTYPE_COMPLEX, "sfo_you", "sfo_you" }, + { 0, NHTYPE_SIMPLE, "sfi_any", "sfi_any" }, + { 0, NHTYPE_SIMPLE, "sfi_aligntyp", "Sfi_aligntyp" }, + { 0, NHTYPE_SIMPLE, "sfi_Bitfield", "Sfi_Bitfield" }, + { 0, NHTYPE_SIMPLE, "sfi_boolean", "Sfi_boolean" }, + { 0, NHTYPE_SIMPLE, "sfi_char", "Sfi_char" }, + { 0, NHTYPE_SIMPLE, "sfi_coordxy", "Sfi_Coordxy" }, + { 0, NHTYPE_SIMPLE, "sfi_int", "Sfi_int32" }, + { 0, NHTYPE_SIMPLE, "sfi_long", "Sfi_long" }, + { 0, NHTYPE_SIMPLE, "sfi_schar", "Sfi_schar" }, + { 0, NHTYPE_SIMPLE, "sfi_short", "Sfi_int16" }, + { 0, NHTYPE_SIMPLE, "sfi_size_t", "Sfi_size_t" }, + { 0, NHTYPE_SIMPLE, "sfi_string", "Sfi_string" }, + { 0, NHTYPE_SIMPLE, "sfi_time_t", "Sfi_time_t" }, + { 0, NHTYPE_SIMPLE, "sfi_uchar", "Sfi_uchar" }, + { 0, NHTYPE_SIMPLE, "sfi_unsigned", "Sfi_uint32" }, + { 0, NHTYPE_SIMPLE, "sfi_xint16", "Sfi_int16" }, + { 0, NHTYPE_SIMPLE, "sfi_xint8", "Sfi_xint8" }, + { 0, NHTYPE_SIMPLE, "sfo_aligntyp", "Sfo_aligntyp" }, + { 0, NHTYPE_SIMPLE, "sfo_any", "Sfo_any" }, + { 0, NHTYPE_SIMPLE, "sfo_Bitfield", "Sfo_Bitfield" }, + { 0, NHTYPE_SIMPLE, "sfo_boolean", "Sfo_boolean" }, + { 0, NHTYPE_SIMPLE, "sfo_char", "Sfo_char" }, + { 0, NHTYPE_SIMPLE, "sfo_coordxy", "Sfo_coordxy" }, + { 0, NHTYPE_SIMPLE, "sfo_int", "Sfo_int32" }, + { 0, NHTYPE_SIMPLE, "sfo_long", "sfo_long" }, + { 0, NHTYPE_SIMPLE, "sfo_schar", "Sfo_schar" }, + { 0, NHTYPE_SIMPLE, "sfo_short", "Sfo_short" }, + { 0, NHTYPE_SIMPLE, "sfo_size_t", "Sfo_size_t" }, + { 0, NHTYPE_SIMPLE, "sfo_string", "Sfo_string" }, + { 0, NHTYPE_SIMPLE, "sfo_time_t", "Sfo_time_t" }, + { 0, NHTYPE_SIMPLE, "sfo_uchar", "Sfo_uchar" }, + { 0, NHTYPE_SIMPLE, "sfo_unsigned", "Sfo_uint32" }, + { 0, NHTYPE_SIMPLE, "sfo_xint16", "Sfo_int16" }, + { 0, NHTYPE_SIMPLE, "sfo_xint8", "Sfo_xint8" } +}; + + /*sftags.c*/ + +