summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog20
-rwxr-xr-xconfigure86
-rw-r--r--eval.c1
-rw-r--r--lib.c52
-rw-r--r--lib.h3
-rw-r--r--txr.112
6 files changed, 160 insertions, 14 deletions
diff --git a/ChangeLog b/ChangeLog
index d0573ac8..0dac1905 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,23 @@
+2013-11-29 Kaz Kylheku <kaz@kylheku.com>
+
+ * configure (config_flags): New variable, allowing us to
+ have stricter diagnosis for configure tests.
+ (have_timegm, need_svid_source, need_bsd_source): New
+ variables. sys/stat.h test only declares static data and
+ compiles an object file. Adding tests for timegm, tzset,
+ setenv and unsetenv.
+
+ * eval.c (eval_init): Register new intrinsic, make_time_utc.
+
+ * lib.c (make_time_impl): New static function.
+ (make_time): Reimplemented as call to make_time_impl.
+ (timegm_hack): New conditionally-defined static function.
+ (make_time_utc): New function.
+
+ * lib.h (make_time_utc): Declared.
+
+ * txr.1: make-time-utc documented.
+
2013-11-28 Kaz Kylheku <kaz@kylheku.com>
* lib.c (make_time): We must subtract from the 1-12
diff --git a/configure b/configure
index e318ef17..51e067a9 100755
--- a/configure
+++ b/configure
@@ -84,6 +84,7 @@ opt_flags=-O2
lang_flags='-ansi -D_XOPEN_SOURCE=2'
diag_flags='-Wall -Wmissing-prototypes -Wstrict-prototypes'
debug_flags=-g
+config_flags=' -Werror' # special: used only during configure
inline=
platform_flags=
remove_flags=
@@ -98,6 +99,9 @@ mpi_version=1.8.6
have_quilt=
have_patch=
have_unistd=
+have_timegm=
+need_svid_source=
+need_bsd_source=
#
# Parse configuration variables
@@ -583,7 +587,7 @@ NM := $nm
OPT_FLAGS := $opt_flags
LANG_FLAGS := $lang_flags
-DIAG_FLAGS := $diag_flags
+DIAG_FLAGS := $diag_flags$config_flags
DBG_FLAGS := $debug_flags
PLATFORM_FLAGS := $platform_flags
REMOVE_FLAGS := $remove_flags
@@ -1152,14 +1156,10 @@ printf "Checking whether we have <sys/stat.h> ... "
cat > conftest.c <<!
#include <sys/stat.h>
-int main(void)
-{
- struct stat s;
- return 0;
-}
+struct stat s;
!
rm -f conftest
-if ! $make conftest > conftest.err 2>&1 || ! [ -x conftest ] ; then
+if ! $make conftest.o > conftest.err 2>&1; then
printf "no\n"
else
printf "yes\n"
@@ -1250,7 +1250,7 @@ fi
# Check for fields inside struct tm
#
-printf "Printf detecting timezone fields in struct tm ..."
+printf "Printf detecting timezone fields in struct tm ... "
tm_gmtoff=
tm_tmzone=
@@ -1283,6 +1283,69 @@ done
printf "done\n"
+printf "Checking for timegm function ... "
+
+cat > conftest.c <<!
+#include <time.h>
+
+int main(void)
+{
+ struct tm tms = { 0 };
+ timegm(&tms);
+ return 0;
+}
+!
+rm -f conftest
+if ! $make EXTRA_FLAGS='-D_SVID_SOURCE' conftest > conftest.err 2>&1 || ! [ -x conftest ] ; then
+ printf "no\n"
+else
+ printf "yes\n"
+ printf "#define HAVE_TIMEGM 1\n" >> config.h
+ have_timegm=y
+ need_svid_source=y
+fi
+
+if [ -z "$have_timegm" ] ; then
+ printf "Checking for setenv and unsetenv functions ... "
+
+ cat > conftest.c <<!
+#include <stdlib.h>
+
+int main(void)
+{
+ setenv("TERM", "foo", 1);
+ unsetenv("TERM");
+ return 0;
+}
+!
+ rm -f conftest
+ if ! $make EXTRA_FLAGS='-D_BSD_SOURCE' conftest > conftest.err 2>&1 || ! [ -x conftest ] ; then
+ printf "no\n"
+ else
+ printf "yes\n"
+ printf "#define HAVE_SETENV 1\n" >> config.h
+ need_bsd_source=y
+ fi
+fi
+printf "Checking for tzset function ... "
+
+cat > conftest.c <<!
+#include <time.h>
+
+int main(void)
+{
+ tzset();
+ return 0;
+}
+!
+rm -f conftest
+if ! $make conftest > conftest.err 2>&1 || ! [ -x conftest ] ; then
+ printf "no\n"
+else
+ printf "yes\n"
+ printf "#define HAVE_TZSET 1\n" >> config.h
+fi
+
printf "Checking for POSIX sleep function ... "
cat > conftest.c <<!
@@ -1423,6 +1486,13 @@ fi
#
printf "Regenerating config.make ... "
+config_flags=
+if [ -n "$need_svid_source" ] ; then
+ lang_flags="$lang_flags -D_SVID_SOURCE"
+fi
+if [ -n "$need_bsd_source" ] ; then
+ lang_flags="$lang_flags -D_BSD_SOURCE"
+fi
gen_config_make
printf "done\n"
diff --git a/eval.c b/eval.c
index 4886856c..c6073f0a 100644
--- a/eval.c
+++ b/eval.c
@@ -2548,6 +2548,7 @@ void eval_init(void)
reg_fun(intern(lit("time-string-local"), user_package), func_n2(time_string_local));
reg_fun(intern(lit("time-string-utc"), user_package), func_n2(time_string_utc));
reg_fun(intern(lit("make-time"), user_package), func_n7(make_time));
+ reg_fun(intern(lit("make-time-utc"), user_package), func_n7(make_time_utc));
reg_fun(intern(lit("errno"), user_package), func_n1o(errno_wrap, 0));
reg_fun(intern(lit("daemon"), user_package), func_n2(daemon_wrap));
diff --git a/lib.c b/lib.c
index 4dfd83d7..0dba8f8f 100644
--- a/lib.c
+++ b/lib.c
@@ -5027,9 +5027,10 @@ val time_string_utc(val time, val format)
return timestr;
}
-val make_time(val year, val month, val day,
- val hour, val minute, val second,
- val isdst)
+static val make_time_impl(time_t (*pmktime)(struct tm *),
+ val year, val month, val day,
+ val hour, val minute, val second,
+ val isdst)
{
struct tm local = { 0 };
time_t time;
@@ -5048,11 +5049,54 @@ val make_time(val year, val month, val day,
else
local.tm_isdst = 1;
- time = mktime(&local);
+ time = pmktime(&local);
return time == -1 ? nil : num(time);
}
+val make_time(val year, val month, val day,
+ val hour, val minute, val second,
+ val isdst)
+{
+ return make_time_impl(mktime, year, month, day, hour, minute, second, isdst);
+}
+
+#if !HAVE_TIMEGM
+static time_t timegm_hack(struct tm *tm)
+{
+ time_t ret;
+ char *tz;
+
+ tz = getenv("TZ");
+ setenv("TZ", "UTC", 1);
+#if HAVE_TZSET
+ tzset();
+#endif
+ ret = mktime(tm);
+ if (tz)
+ setenv("TZ", tz, 1);
+ else
+ unsetenv("TZ");
+#if HAVE_TZSET
+ tzset();
+#endif
+ return ret;
+}
+#endif
+
+val make_time_utc(val year, val month, val day,
+ val hour, val minute, val second,
+ val isdst)
+{
+#if HAVE_TIMEGM
+ time_t (*pmktime)(struct tm *) = timegm;
+#else
+ time_t (*pmktime)(struct tm *) = timegm_hack;
+#endif
+
+ return make_time_impl(pmktime, year, month, day, hour, minute, second, isdst);
+}
+
void init(const wchar_t *pn, mem_t *(*oom)(mem_t *, size_t),
val *stack_bottom)
{
diff --git a/lib.h b/lib.h
index ac791ae9..c4a7f2df 100644
--- a/lib.h
+++ b/lib.h
@@ -682,6 +682,9 @@ val time_string_utc(val time, val format);
val make_time(val year, val month, val day,
val hour, val minute, val second,
val isdst);
+val make_time_utc(val year, val month, val day,
+ val hour, val minute, val second,
+ val isdst);
void init(const wchar_t *progname, mem_t *(*oom_realloc)(mem_t *, size_t),
val *stack_bottom);
diff --git a/txr.1 b/txr.1
index a647cf53..45780d73 100644
--- a/txr.1
+++ b/txr.1
@@ -1,4 +1,4 @@
-.\"Copyright (C) 2011, Kaz Kylheku <kaz@kylheku.com>.
+.\"Copyright (C) 20114 Kaz Kylheku <kaz@kylheku.com>.
.\"All rights reserved.
.\"
.\"BSD License:
@@ -10775,12 +10775,13 @@ the format string of the C library function strftime.
The <time> argument is an integer representing seconds obtained from the
time function or from the time-usec function.
-.SS Function make-time
+.SS Functions make-time and make-time-utc
.TP
Syntax:
(make-time <year> <month> <day> <hour> <minute> <second> <dst-advice>)
+ (make-time-utc <year> <month> <day> <hour> <minute> <second> <dst-advice>)
.TP
Description
@@ -10800,6 +10801,13 @@ If the argument is nil, then the time is assumed not to be in DST.
If <dst-advice> is :auto, then the function tries to determine whether
DST is in effect in the current time zone for the specified date and time.
+The make-time-utc function is similar to make-time, except that
+it treats the time as UTC rather than in the local time zone.
+The <dst-advice> argument is supported by make-time-utc for function
+call compatibility with make-time. It may or may not have any effect
+on the output (since the UTC zone by definition doesn't have daylight
+savings time).
+
.SH UNIX PROGRAMMING
.SS Functions errno and set-errno