memory management for 'nomakedefs'
The nomakedefs struct starts out with static values, then if/when populate_nomakedefs() is called, the fields are given dynamic values. free_nomakedefs() needs to know what state it's in. A big chunk of this if just formatting for indentation.
This commit is contained in:
136
src/date.c
136
src/date.c
@@ -1,4 +1,4 @@
|
||||
/* NetHack 3.7 date.c $NHDT-Date: 1644524054 2022/02/10 20:14:14 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.1 $ */
|
||||
/* NetHack 3.7 date.c $NHDT-Date: 1645393645 2022/02/20 21:47:25 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.2 $ */
|
||||
/* Copyright (c) Michael Allison, 2021. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
@@ -17,6 +17,9 @@ extern char *version_id_string(char *, int, const char *);
|
||||
extern char *bannerc_string(char *, int, const char *);
|
||||
extern int case_insensitive_comp(const char *, const char *);
|
||||
|
||||
/* nomakedefs_populated: flag for whether 'nomakedefs' should be freed */
|
||||
static int nomakedefs_populated = 0;
|
||||
|
||||
struct nomakedefs_s nomakedefs = {
|
||||
/* https://groups.google.com/forum/#!original/
|
||||
comp.sources.games/91SfKYg_xzI/dGnR3JnspFkJ */
|
||||
@@ -54,79 +57,88 @@ populate_nomakedefs(struct version_info *version)
|
||||
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
|
||||
struct tm t = {0};
|
||||
time_t timeresult;
|
||||
/*
|
||||
* In a cross-compiled environment, you can't execute
|
||||
* the target binaries during the build, so we can't
|
||||
* use makedefs to write the values of the build
|
||||
* date and time to a file for retrieval. Not for
|
||||
* information meaningful to the target execution
|
||||
* environment.
|
||||
*
|
||||
* How can we capture the build date/time of the target
|
||||
* binaries in such a situation? We need to rely on the
|
||||
* cross-compiler itself to do it for us during the
|
||||
* cross-compile.
|
||||
*
|
||||
* To that end, we are going to make use of the
|
||||
* following pre-defined preprocessor macros for this:
|
||||
* gcc, msvc, clang __DATE__ "Feb 12 1996"
|
||||
* gcc, msvc, clang __TIME__ "23:59:01"
|
||||
*
|
||||
*/
|
||||
/* if (sizeof __DATE__ + sizeof __TIME__ + sizeof "123" <
|
||||
sizeof tmpbuf1) */
|
||||
Snprintf(tmpbuf1, sizeof tmpbuf1, "%s %s", __DATE__, __TIME__);
|
||||
/* "Feb 12 1996 23:59:01"
|
||||
01234567890123456789 */
|
||||
if ((int) strlen(tmpbuf1) == 20) {
|
||||
extract_field(tmpbuf2, tmpbuf1, 4, 7); /* year */
|
||||
t.tm_year = atoi(tmpbuf2) - 1900;
|
||||
extract_field(tmpbuf2, tmpbuf1, 3, 0); /* mon */
|
||||
for (i = 0; i < SIZE(mth); ++i)
|
||||
if (!case_insensitive_comp(tmpbuf2, mth[i])) {
|
||||
t.tm_mon = i;
|
||||
break;
|
||||
}
|
||||
extract_field(tmpbuf2, tmpbuf1, 2, 4); /* mday */
|
||||
strp = tmpbuf2;
|
||||
if (*strp == ' ')
|
||||
strp++;
|
||||
t.tm_mday = atoi(strp);
|
||||
extract_field(tmpbuf2, tmpbuf1, 2, 12); /* hour */
|
||||
t.tm_hour = atoi(tmpbuf2);
|
||||
extract_field(tmpbuf2, tmpbuf1, 2, 15); /* min */
|
||||
t.tm_min = atoi(tmpbuf2);
|
||||
extract_field(tmpbuf2, tmpbuf1, 2, 18); /* sec */
|
||||
t.tm_sec = atoi(tmpbuf2);
|
||||
timeresult = mktime(&t);
|
||||
nomakedefs.build_time = (unsigned long) timeresult;
|
||||
nomakedefs.build_date = dupstr(tmpbuf1);
|
||||
}
|
||||
|
||||
nomakedefs.version_number = version->incarnation;
|
||||
nomakedefs.version_features = version->feature_set;
|
||||
/*
|
||||
* In a cross-compiled environment, you can't execute
|
||||
* the target binaries during the build, so we can't
|
||||
* use makedefs to write the values of the build
|
||||
* date and time to a file for retrieval. Not for
|
||||
* information meaningful to the target execution
|
||||
* environment.
|
||||
*
|
||||
* How can we capture the build date/time of the target
|
||||
* binaries in such a situation? We need to rely on the
|
||||
* cross-compiler itself to do it for us during the
|
||||
* cross-compile.
|
||||
*
|
||||
* To that end, we are going to make use of the
|
||||
* following pre-defined preprocessor macros for this:
|
||||
* gcc, msvc, clang __DATE__ "Feb 12 1996"
|
||||
* gcc, msvc, clang __TIME__ "23:59:01"
|
||||
*
|
||||
*/
|
||||
|
||||
Snprintf(tmpbuf1, sizeof tmpbuf1, "%s %s", __DATE__, __TIME__);
|
||||
/* "Feb 12 1996 23:59:01"
|
||||
01234567890123456789 */
|
||||
if ((int) strlen(tmpbuf1) == 20) {
|
||||
extract_field(tmpbuf2, tmpbuf1, 4, 7); /* year */
|
||||
t.tm_year = atoi(tmpbuf2) - 1900;
|
||||
extract_field(tmpbuf2, tmpbuf1, 3, 0); /* mon */
|
||||
for (i = 0; i < SIZE(mth); ++i)
|
||||
if (!case_insensitive_comp(tmpbuf2, mth[i])) {
|
||||
t.tm_mon = i;
|
||||
break;
|
||||
}
|
||||
extract_field(tmpbuf2, tmpbuf1, 2, 4); /* mday */
|
||||
strp = tmpbuf2;
|
||||
if (*strp == ' ')
|
||||
strp++;
|
||||
t.tm_mday = atoi(strp);
|
||||
extract_field(tmpbuf2, tmpbuf1, 2, 12); /* hour */
|
||||
t.tm_hour = atoi(tmpbuf2);
|
||||
extract_field(tmpbuf2, tmpbuf1, 2, 15); /* min */
|
||||
t.tm_min = atoi(tmpbuf2);
|
||||
extract_field(tmpbuf2, tmpbuf1, 2, 18); /* sec */
|
||||
t.tm_sec = atoi(tmpbuf2);
|
||||
timeresult = mktime(&t);
|
||||
nomakedefs.build_time = (unsigned long) timeresult;
|
||||
nomakedefs.build_date = dupstr(tmpbuf1);
|
||||
}
|
||||
|
||||
nomakedefs.version_number = version->incarnation;
|
||||
nomakedefs.version_features = version->feature_set;
|
||||
#ifdef MD_IGNORED_FEATURES
|
||||
nomakedefs.ignored_features = MD_IGNORED_FEATURES;
|
||||
nomakedefs.ignored_features = MD_IGNORED_FEATURES;
|
||||
#endif
|
||||
nomakedefs.version_sanity1 = version->entity_count;
|
||||
nomakedefs.version_sanity2 = version->struct_sizes1;
|
||||
nomakedefs.version_sanity3 = version->struct_sizes2;
|
||||
nomakedefs.version_string = dupstr(mdlib_version_string(tmpbuf2, "."));
|
||||
nomakedefs.version_id = dupstr(
|
||||
nomakedefs.version_sanity1 = version->entity_count;
|
||||
nomakedefs.version_sanity2 = version->struct_sizes1;
|
||||
nomakedefs.version_sanity3 = version->struct_sizes2;
|
||||
nomakedefs.version_string = dupstr(mdlib_version_string(tmpbuf2, "."));
|
||||
nomakedefs.version_id = dupstr(
|
||||
version_id_string(tmpbuf2, sizeof tmpbuf2, nomakedefs.build_date));
|
||||
nomakedefs.copyright_banner_c = dupstr(
|
||||
nomakedefs.copyright_banner_c = dupstr(
|
||||
bannerc_string(tmpbuf2, sizeof tmpbuf2, nomakedefs.build_date));
|
||||
#ifdef NETHACK_GIT_SHA
|
||||
nomakedefs.git_sha = dupstr(NETHACK_GIT_SHA);
|
||||
nomakedefs.git_sha = dupstr(NETHACK_GIT_SHA);
|
||||
#endif
|
||||
#ifdef NETHACK_GIT_BRANCH
|
||||
nomakedefs.git_branch = dupstr(NETHACK_GIT_BRANCH);
|
||||
nomakedefs.git_branch = dupstr(NETHACK_GIT_BRANCH);
|
||||
#endif
|
||||
|
||||
nomakedefs_populated = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
free_nomakedefs(void)
|
||||
{
|
||||
/* can't just free non-Null values because they're initialized at
|
||||
compile-time with static strings and won't have dynamic values
|
||||
unless populate_nomakedefs() has been called */
|
||||
if (!nomakedefs_populated)
|
||||
return;
|
||||
|
||||
if (nomakedefs.build_date)
|
||||
free((genericptr_t) nomakedefs.build_date),
|
||||
nomakedefs.build_date = 0;
|
||||
@@ -149,6 +161,10 @@ free_nomakedefs(void)
|
||||
free((genericptr_t) nomakedefs.git_branch),
|
||||
nomakedefs.git_branch = 0;
|
||||
#endif
|
||||
|
||||
/* values are Null now; dynamic vs static doesn't really matter anymore */
|
||||
nomakedefs_populated = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
#endif /* __DATE__ && __TIME__ */
|
||||
|
||||
Reference in New Issue
Block a user