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
This commit is contained in:
H. Peter Anvin 2008-02-16 14:54:10 -08:00
parent 188ce76c46
commit 6b18bcce46
3 changed files with 146 additions and 6 deletions

View File

@ -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

92
nasm.c
View File

@ -15,6 +15,7 @@
#include <ctype.h>
#include <inttypes.h>
#include <limits.h>
#include <time.h>
#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\"", &lt);
pp_pre_define(temp);
strftime(temp, sizeof temp, "__DATE_NUM__=%Y%m%d", &lt);
pp_pre_define(temp);
strftime(temp, sizeof temp, "__TIME__=\"%H:%M:%S\"", &lt);
pp_pre_define(temp);
strftime(temp, sizeof temp, "__TIME_NUM__=%H%M%S", &lt);
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(&lt);
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:

10
test/time.asm Normal file
View File

@ -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__