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*/ + +