From 6b18bcce46629fb03c4d14b7f83e158815ae29d7 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Sat, 16 Feb 2008 14:54:10 -0800 Subject: [PATCH] BR 774131: date and time macros This checkin creates the following date and time macros: __DATE__, __TIME__, __UTC_DATE__, __UTC_TIME__: strings __DATE_NUM__, __TIME_NUM__, __UTC_DATE_NUM__, __UTC_TIME_NUM__: civil dates in digit-string formats __POSIX_TIME__: time in POSIX time_t format --- doc/nasmdoc.src | 50 +++++++++++++++++++++++++++ nasm.c | 92 +++++++++++++++++++++++++++++++++++++++++++++---- test/time.asm | 10 ++++++ 3 files changed, 146 insertions(+), 6 deletions(-) create mode 100644 test/time.asm diff --git a/doc/nasmdoc.src b/doc/nasmdoc.src index a86ca8d1..22065d12 100644 --- a/doc/nasmdoc.src +++ b/doc/nasmdoc.src @@ -3111,6 +3111,56 @@ number of 16, 32 or 64. \c{__BITS__} receives the specified mode number and makes it globally available. This can be very useful for those who utilize mode-dependent macros. +\S{datetime} \i\c{__DATE__} and \i\c{__TIME__}: Assembly date and time + +The \c{__DATE__} and \c{__TIME__} macros give the assembly date and +time as strings, in ISO 8601 format (\c{"YYYY-MM-DD"} and \c{"HH:MM:SS"}, +respectively.) + +All instances of time and date macros in the same assembly session +produce consistent output. + +\S{datetimenum} \i\c{__DATE_NUM__} and \i\c{__TIME_NUM__}: Numeric +assembly date and time + +The \c{__DATE_NUM__} and \c{__TIME_NUM__} macros give the assembly +date and time in numeric form; in the format \c{YYYYMMDD} and +\c{HHMMSS} respectively. + +All instances of time and date macros in the same assembly session +produce consistent output. + +\S{utcdatetime} \i\c{__UTC_DATE__} and \i\c{__UTC_TIME__}: Assembly UTC date and time + +The \c{__DATE__} and \c{__TIME__} macros give the assembly date and +time in universal time (UTC) as strings, in ISO 8601 format +(\c{"YYYY-MM-DD"} and \c{"HH:MM:SS"}, respectively.) If the +underlying platform doesn't provide UTC time, these macros are +undefined. + +All instances of time and date macros in the same assembly session +produce consistent output. + +\S{utcdatetimenum} \i\c{__UTC_DATE_NUM__} and \i\c{__UTC_TIME_NUM__}: Numeric +assembly UTC date and time + +The \c{__UTC_DATE_NUM__} and \c{__UTC_TIME_NUM__} macros give the +assembly date and time universal time (UTC) in numeric form; in the +format \c{YYYYMMDD} and \c{HHMMSS} respectively. If the +underlying platform doesn't provide UTC time, these macros are +undefined. + +All instances of time and date macros in the same assembly session +produce consistent output. + +\S{posixtime} \i\c{__POSIX_TIME__}: POSIX time constant + +The \c{__POSIX_TIME__} macro is defined as a number containing the +number of seconds since the POSIX epoch, 1 January 1970 00:00:00 UTC; +excluding any leap seconds. + +This is computed using UTC time if available on the platform, +otherwise it is computed using the local time as if it was UTC. \S{struc} \i\c{STRUC} and \i\c{ENDSTRUC}: \i{Declaring Structure} Data Types diff --git a/nasm.c b/nasm.c index 9c4cd9ba..2af74ef1 100644 --- a/nasm.c +++ b/nasm.c @@ -15,6 +15,7 @@ #include #include #include +#include #include "nasm.h" #include "nasmlib.h" @@ -53,6 +54,8 @@ int pass0, passn; int maxbits = 0; int globalrel = 0; +time_t official_compile_time; + static char inname[FILENAME_MAX]; static char outname[FILENAME_MAX]; static char listname[FILENAME_MAX]; @@ -160,8 +163,86 @@ static void nasm_fputs(const char *line, FILE * outfile) puts(line); } +/* Convert a struct tm to a POSIX-style time constant */ +static int64_t posix_mktime(struct tm *tm) +{ + int64_t t; + int64_t y = tm->tm_year; + + /* See IEEE 1003.1:2004, section 4.14 */ + + t = (y-70)*365 + (y-69)/4 - (y-1)/100 + (y+299)/400; + t += tm->tm_yday; + t *= 24; + t += tm->tm_hour; + t *= 60; + t += tm->tm_min; + t *= 60; + t += tm->tm_sec; + + return t; +} + +static void define_macros_early(void) +{ + char temp[128]; + struct tm lt, *lt_p, gm, *gm_p; + int64_t posix_time; + + lt_p = localtime(&official_compile_time); + if (lt_p) { + lt = *lt_p; + + strftime(temp, sizeof temp, "__DATE__=\"%Y-%m-%d\"", <); + pp_pre_define(temp); + strftime(temp, sizeof temp, "__DATE_NUM__=%Y%m%d", <); + pp_pre_define(temp); + strftime(temp, sizeof temp, "__TIME__=\"%H:%M:%S\"", <); + pp_pre_define(temp); + strftime(temp, sizeof temp, "__TIME_NUM__=%H%M%S", <); + pp_pre_define(temp); + } + + gm_p = gmtime(&official_compile_time); + if (gm_p) { + gm = *gm_p; + + strftime(temp, sizeof temp, "__UTC_DATE__=\"%Y-%m-%d\"", &gm); + pp_pre_define(temp); + strftime(temp, sizeof temp, "__UTC_DATE_NUM__=%Y%m%d", &gm); + pp_pre_define(temp); + strftime(temp, sizeof temp, "__UTC_TIME__=\"%H:%M:%S\"", &gm); + pp_pre_define(temp); + strftime(temp, sizeof temp, "__UTC_TIME_NUM__=%H%M%S", &gm); + pp_pre_define(temp); + } + + if (gm_p) + posix_time = posix_mktime(&gm); + else if (lt_p) + posix_time = posix_mktime(<); + else + posix_time = 0; + + if (posix_time) { + snprintf(temp, sizeof temp, "__POSIX_TIME__=%"PRId64, posix_time); + pp_pre_define(temp); + } +} + +static void define_macros_late(void) +{ + char temp[128]; + + snprintf(temp, sizeof(temp), "__OUTPUT_FORMAT__=%s\n", + ofmt->shortname); + pp_pre_define(temp); +} + int main(int argc, char **argv) { + time(&official_compile_time); + pass0 = 1; want_usage = terminate_after_phase = false; report_error = report_error_gnu; @@ -179,6 +260,10 @@ int main(int argc, char **argv) register_output_formats(); + /* Define some macros dependent on the runtime, but not + on the command line. */ + define_macros_early(); + parse_cmdline(argc, argv); if (terminate_after_phase) { @@ -197,12 +282,7 @@ int main(int argc, char **argv) eval_global_info(ofmt, lookup_label, &location); /* define some macros dependent of command-line */ - { - char temp[64]; - snprintf(temp, sizeof(temp), "__OUTPUT_FORMAT__=%s\n", - ofmt->shortname); - pp_pre_define(temp); - } + define_macros_late(); switch (operating_mode) { case op_depend_missing_ok: diff --git a/test/time.asm b/test/time.asm new file mode 100644 index 00000000..fa1dd296 --- /dev/null +++ b/test/time.asm @@ -0,0 +1,10 @@ + db __DATE__, 13, 10 + db __TIME__, 13, 10 + db __UTC_DATE__, 13, 10 + db __UTC_TIME__, 13, 10 + align 4 + dd __DATE_NUM__ + dd __TIME_NUM__ + dd __UTC_DATE_NUM__ + dd __UTC_TIME_NUM__ + dd __POSIX_TIME__