[m-dev.] for review: add `time' module to standard library
Fergus Henderson
fjh at cs.mu.OZ.AU
Thu Oct 28 01:55:06 AEST 1999
Estimated hours taken: 3
(plus unknown time by Thomas By)
library/time.m:
New module, originally written by Thomas By <T.By at dcs.shef.ac.uk>.
This provides an interface to the ANSI/ISO C time functions.
I have made the following changes to Thomas By's version:
* bug fixes:
- fixed a bug where it had `will_not_call_mercury'
instead of `may_call_mercury' in a couple of places;
the fix was to change the code to use
MR_make_aligned_string_copy() rather than
calling builtin__copy/2 via `pragma export'.
- fixed a bug where it was casting an `Integer *'
to a `time_t *'; that won't have the desired effect
if `Integer' and `time_t' are not the same size.
* interface changes:
- changed the clocks_per_second procedure so that
it did not take any io__state arguments
(that's safe, since ANSI/ISO C requires the
CLOCKS_PER_SECOND macro to be a constant expression)
- changed the DST field from `maybe(bool)' to `maybe(dst)',
where `dst' is an enumeration type defined as
`:- type dst ---> standard_time ; daylight_time'.
- changed all the predicates with only one output
into functions
- changed the code to throw exceptions on failure rather
than returning results of type `io__res(T)'
* stylistic changes:
- modified the layout to match our standard
Mercury coding conventions
- added a more detailed copyright notice
library/library.m:
Add `time' to the list of modules in the standard library.
configure.in:
runtime/mercury_conf.h.in:
Add autoconf checks for <sys/times.h> and for the
struct tms type and the times() function.
runtime/mercury_string.h:
runtime/mercury_bootstrap.h:
Add `MR_' prefixes to a few macros, so that the new code
in library/time.m doesn't need to use the old versions.
Define the old names as aliases for the new ones
in mercury_bootstrap.h.
NEWS:
w3/news/newsdb.inc:
Mention the new module.
Workspace: /home/mercury0/fjh/mercury
Index: NEWS
===================================================================
RCS file: /home/mercury1/repository/mercury/NEWS,v
retrieving revision 1.150
diff -u -d -r1.150 NEWS
--- NEWS 1999/10/26 09:57:39 1.150
+++ NEWS 1999/10/27 15:30:02
@@ -73,6 +73,12 @@
However, many of the operations in the standard library still handle
errors by aborting execution rather than by throwing exceptions.
+* There's a new standard library module `time'.
+
+ The `time' module provides an interface to the ANSI/ISO C <time.h>
+ functions, and to the POSIX times() function. Thanks to Thomas By
+ for contributing the original version of this module.
+
* There's a new standard library module `gc', for controlling the
garbage collector.
Index: configure.in
===================================================================
RCS file: /home/mercury1/repository/mercury/configure.in,v
retrieving revision 1.185
diff -u -d -r1.185 configure.in
--- configure.in 1999/10/24 08:38:54 1.185
+++ configure.in 1999/10/27 14:52:42
@@ -262,6 +262,16 @@
AC_DEFINE(HAVE_SYS_TIME)
fi
#-----------------------------------------------------------------------------#
+AC_CHECK_HEADER(sys/times.h, HAVE_SYS_TIMES_H=1)
+if test "$HAVE_SYS_TIMES_H" = 1; then
+ AC_DEFINE(HAVE_SYS_TIMES_H)
+fi
+#-----------------------------------------------------------------------------#
+AC_CHECK_HEADER(sys/types.h, HAVE_SYS_TYPES_H=1)
+if test "$HAVE_SYS_TYPES_H" = 1; then
+ AC_DEFINE(HAVE_SYS_TYPES_H)
+fi
+#-----------------------------------------------------------------------------#
AC_CHECK_HEADER(sys/stat.h, HAVE_SYS_STAT_H=1)
if test "$HAVE_SYS_STAT_H" = 1; then
AC_DEFINE(HAVE_SYS_STAT_H)
@@ -2028,6 +2038,39 @@
AC_SUBST_FILE(INIT_GRADE_OPTIONS)
AC_SUBST_FILE(PARSE_GRADE_OPTIONS)
AC_SUBST_FILE(FINAL_GRADE_OPTIONS)
+
+#-----------------------------------------------------------------------------#
+#
+# Check for the POSIX struct tms and times() function.
+# This is used for the time__times procedure in library/times.m.
+#
+AC_MSG_CHECKING(for struct tms and times function)
+AC_CACHE_VAL(mercury_cv_have_posix_times,
+AC_TRY_LINK([
+ #include <sys/types.h>
+ #include <sys/times.h>
+],[
+ struct tms t;
+ long Ut, St, CUt, CSt;
+ long Ret;
+
+ Ret = (long) times(&t);
+
+ Ut = (long) t.tms_utime;
+ St = (long) t.tms_stime;
+ CUt = (long) t.tms_cutime;
+ CSt = (long) t.tms_cstime;
+],[mercury_cv_have_posix_times=yes],[mercury_cv_have_posix_times=no]))
+
+#
+# figure out whether the test succeeded
+#
+if test "$mercury_cv_have_posix_times" = yes; then
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(MR_HAVE_POSIX_TIMES)
+else
+ AC_MSG_RESULT(no)
+fi
#-----------------------------------------------------------------------------#
#
Index: library/library.m
===================================================================
RCS file: /home/mercury1/repository/mercury/library/library.m,v
retrieving revision 1.45
diff -u -d -r1.45 library.m
--- library.m 1999/10/06 06:02:59 1.45
+++ library.m 1999/10/27 12:35:00
@@ -34,6 +34,7 @@
:- import_module prolog.
:- import_module integer, rational.
:- import_module exception, gc.
+:- import_module time.
% library__version must be implemented using pragma c_code,
% so we can get at the MR_VERSION and MR_FULLARCH configuration
cvs diff: library/time.m is a new entry, no comparison available
Index: runtime/mercury_bootstrap.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_bootstrap.h,v
retrieving revision 1.11
diff -u -d -r1.11 mercury_bootstrap.h
--- mercury_bootstrap.h 1999/10/26 13:41:10 1.11
+++ mercury_bootstrap.h 1999/10/27 15:10:20
@@ -27,6 +27,11 @@
#define COMPARE_LESS MR_COMPARE_LESS
#define COMPARE_GREATER MR_COMPARE_GREATER
+#define make_aligned_string_copy(a,b) MR_make_aligned_string_copy((a),(b))
+#define make_aligned_string(a,b) MR_make_aligned_string((a),(b))
+#define string_equal(a,b) MR_string_equal((a),(b))
+#define string_const(a,b) MR_string_const((a),(b))
+
/*
** The list manipulation macros are available for use by ordinary Mercury
** programmers. People may have written code using these macros before their
Index: runtime/mercury_conf.h.in
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_conf.h.in,v
retrieving revision 1.23
diff -u -d -r1.23 mercury_conf.h.in
--- mercury_conf.h.in 1999/09/23 02:15:09 1.23
+++ mercury_conf.h.in 1999/10/27 13:08:12
@@ -101,6 +101,8 @@
** HAVE_SYS_PARAM we have <sys/param.h>
** HAVE_SYS_WAIT we have <sys/wait.h>
** HAVE_SYS_STAT_H we have <sys/stat.h>
+** HAVE_SYS_TYPES_H we have <sys/types.h>
+** HAVE_SYS_TIMES_H we have <sys/times.h>
** HAVE_DLFCN_H we have <dlfcn.h>
*/
#undef HAVE_SYS_SIGINFO
@@ -111,7 +113,15 @@
#undef HAVE_SYS_PARAM
#undef HAVE_SYS_WAIT
#undef HAVE_SYS_STAT_H
+#undef HAVE_SYS_TIMES_H
+#undef HAVE_SYS_TYPES_H
#undef HAVE_DLFCN_H
+
+/*
+** MR_HAVE_POSIX_TIMES is defined if we have the POSIX
+** `struct tms' struct and times() function.
+*/
+#undef MR_HAVE_POSIX_TIMES
/*
** The following macros are defined iff the corresponding type
Index: runtime/mercury_string.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_string.h,v
retrieving revision 1.13
diff -u -d -r1.13 mercury_string.h
--- mercury_string.h 1999/09/27 05:20:48 1.13
+++ mercury_string.h 1999/10/27 15:09:14
@@ -36,16 +36,16 @@
** string_const("...", len):
** Given a C string literal and its length, returns a Mercury string.
*/
-#define string_const(string, len) ((String) string)
+#define MR_string_const(string, len) ((String) string)
/*
** bool string_equal(ConstString s1, ConstString s2):
** Return true iff the two Mercury strings s1 and s2 are equal.
*/
-#define string_equal(s1,s2) (strcmp((char*)(s1),(char*)(s2))==0)
+#define MR_string_equal(s1,s2) (strcmp((char*)(s1),(char*)(s2))==0)
/*
-** void make_aligned_string(ConstString & ptr, const char * string):
+** void MR_make_aligned_string(ConstString & ptr, const char * string):
** Given a C string `string', set `ptr' to be a Mercury string
** with the same contents. (`ptr' must be an lvalue.)
** If the resulting Mercury string is to be used by Mercury code,
@@ -61,16 +61,16 @@
** Otherwise, allocate space on the heap and copy the C string to
** the Mercury string.
*/
-#define make_aligned_string(ptr, string) \
+#define MR_make_aligned_string(ptr, string) \
do { \
if (MR_tag((Word) (string)) != 0) { \
- make_aligned_string_copy((ptr), (string)); \
+ MR_make_aligned_string_copy((ptr), (string)); \
} else { \
(ptr) = (string); \
} \
} while(0)
-/* void make_aligned_string_copy(ConstString &ptr, const char * string);
+/* void MR_make_aligned_string_copy(ConstString &ptr, const char * string);
** Same as make_aligned_string(ptr, string), except that the string
** is guaranteed to be copied. This is useful for copying C strings
** onto the Mercury heap.
@@ -80,7 +80,7 @@
** rather than inside Mercury code, you may need to call
** save/restore_transient_hp().
*/
-#define make_aligned_string_copy(ptr, string) \
+#define MR_make_aligned_string_copy(ptr, string) \
do { \
Word make_aligned_string_tmp; \
char * make_aligned_string_ptr; \
Index: w3/news/newsdb.inc
===================================================================
RCS file: /home/mercury1/repository/w3/news/newsdb.inc,v
retrieving revision 1.34
diff -u -d -r1.34 newsdb.inc
--- newsdb.inc 1999/09/16 04:01:33 1.34
+++ newsdb.inc 1999/10/27 15:29:17
@@ -17,6 +17,15 @@
*/
$newsdb = array(
+"28 Oct 1999" => array("Time module",
+
+"The standard library now includes a module `time'
+which provides an interface to the ANSI/ISO C <time.h> functions
+and to the POSIX times() function.
+
+Thanks to Thomas By for contributing the original version of this module.
+"),
+
"16 Sep 1999" => array("Exception handling",
"Exception handling support is now part of the standard library.
===================================================================
library/time.m
===================================================================
%-----------------------------------------------------------------------------%
% Originally written in 1999 by Tomas By <T.By at dcs.shef.ac.uk>
% "Feel free to use this code or parts of it any way you want."
%
% Some portions are Copyright (C) 1999 The University of Melbourne.
% This file may only be copied under the terms of the GNU Library General
% Public License - see the file COPYING.LIB in the Mercury distribution.
%-----------------------------------------------------------------------------%
%
% File: time.m.
% Main authors: Tomas By <T.By at dcs.shef.ac.uk>, fjh
% Stability: medium
%
% Time functions.
%
%-----------------------------------------------------------------------------%
:- module time.
:- interface.
:- use_module io.
:- import_module std_util.
:- type clock_t == int.
:- type tms --->
tms(int, % Utime
int, % Stime
int, % CUtime
int). % CStime
:- type time_t == int.
:- type tm --->
tm(int, % Seconds (0-60)
int, % Minutes (0-59)
int, % Hours (after midnight, 0-23)
int, % WeekDay (number since Sunday, 0-6)
int, % YearDay (number since Jan 1st, 0-365)
int, % Month (number since January, 0-11)
int, % Year (number since 1900)
maybe(dst)). % IsDST (is DST in effect?)
:- type dst
---> standard_time % no, DST is not in effect
; daylight_time. % yes, DST is in effect
% Some of the procedures in this module throw this type
% as an exception if they can't obtain a result.
:- type time_error --->
time_error(string). % Error message
%-----------------------------------------------------------------------------%
% time__clock(Result, IO_state, IO_state):
% Returns the elapsed processor time (number of clock
% ticks). The base time is arbitrary but doesn't change
% within a single process.
% If the time cannot be obtained, this procedure
% will throw a time_error exception.
%
:- pred time__clock(clock_t, io__state, io__state).
:- mode time__clock(out, di, uo) is det.
% time__clocks_per_sec:
% Returns the number of clock ticks per second.
%
:- func time__clocks_per_sec = int.
% time__time(Result, IO_state, IO_state):
% Returns the current (simple) calendar time.
% If the time cannot be obtained, this procedure
% will throw a time_error exception.
%
:- pred time__time(time_t, io__state, io__state).
:- mode time__time(out, di, uo) is det.
% time__times(ProcessorTime, ElapsedRealTime, IO_state, IO_state)
% (POSIX)
% Returns the processor time information in the `tms'
% value, and the elapsed real time relative to an
% arbitrary base in the `clock_t' value.
% If the time cannot be obtained, this procedure
% will throw a time_error exception.
%
% On non-POSIX systems that do not support this functionality,
% this procedure may simply always throw an exception.
%
:- pred time__times(tms, clock_t, io__state, io__state).
:- mode time__times(out, out, di, uo) is det.
%-----------------------------------------------------------------------------%
% time__difftime(Time1, Time0) = N:
% Computes the number of seconds elapsed between
% `Time1' and `Time0'.
%
:- func time__difftime(time_t, time_t) = int.
% time__localtime(Time) = TM:
% Converts the calendar time `Time' to a broken-down
% representation, expressed relative to the user's
% specified time zone.
%
:- func time__localtime(time_t) = tm.
% time__mktime(TM) = Time:
% Converts the broken-down time value to calendar time.
% It also normalises the value by filling in day of
% week and day of year based on the other components.
%
:- func time__mktime(tm) = time_t.
%-----------------------------------------------------------------------------%
% time__asctime(TM) = String:
% Converts the broken-down time value `TM' to a string
% in a standard format.
%
:- func time__asctime(tm) = string.
% time__ctime(Time) = String:
% Converts the calendar time value `Time' to a string
% in a standard format.
% (ie same as "asctime (localtime (<time>))")
%
:- func time__ctime(time_t) = string.
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
:- implementation.
:- pragma c_header_code("
#include <time.h>
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_SYS_TIMES_H
#include <sys/times.h>
#endif
").
%-----------------------------------------------------------------------------%
%:- pred time__clock(clock_t, io__state, io__state).
%:- mode time__clock(out, di, uo) is det.
time__clock(Result, IO0, IO) :-
time__c_clock(Ret, IO0, IO),
( Ret = -1 ->
throw(time_error("can't get clock value"))
;
Result = Ret
).
:- pred time__c_clock(int, io__state, io__state).
:- mode time__c_clock(out, di, uo) is det.
:- pragma c_code(time__c_clock(Ret::out, IO0::di, IO::uo),
[will_not_call_mercury],
"{
Ret = (Integer) clock();
update_io(IO0, IO);
}").
%-----------------------------------------------------------------------------%
%:- func time__clocks_per_sec = int.
time__clocks_per_sec = Val :-
time__c_clocks_per_sec(Val).
:- pred time__c_clocks_per_sec(int).
:- mode time__c_clocks_per_sec(out) is det.
:- pragma c_code(time__c_clocks_per_sec(Ret::out),
[will_not_call_mercury],
"{
Ret = (Integer) CLOCKS_PER_SEC;
}").
%-----------------------------------------------------------------------------%
%:- pred time__times(tms, clock_t, io__state, io__state).
%:- mode time__times(out, out, di, uo) is det.
time__times(Tms, Result, IO0, IO) :-
time__c_times(Ret, Ut, St, CUt, CSt, IO0, IO),
( Ret = -1 ->
throw(time_error("can't get times value"))
;
Tms = tms(Ut, St, CUt, CSt),
Result = Ret
).
:- pred time__c_times(int, int, int, int, int, io__state, io__state).
:- mode time__c_times(out, out, out, out, out, di, uo) is det.
:- pragma c_code(time__c_times(Ret::out, Ut::out, St::out, CUt::out,
CSt::out, IO0::di, IO::uo),
[will_not_call_mercury],
"{
#ifdef MR_HAVE_POSIX_TIMES
struct tms t;
Ret = (Integer) times(&t);
Ut = (Integer) t.tms_utime;
St = (Integer) t.tms_stime;
CUt = (Integer) t.tms_cutime;
CSt = (Integer) t.tms_cstime;
#else
Ret = -1
#endif
update_io(IO0, IO);
}").
%-----------------------------------------------------------------------------%
%:- pred time__time(time_t, io__state, io__state).
%:- mode time__time(out, di, uo) is det.
time__time(Result, IO0, IO) :-
time__c_time(Ret, IO0, IO),
( Ret = -1 ->
throw(time_error("can't get time value"))
;
Result = Ret
).
:- pred time__c_time(int, io__state, io__state).
:- mode time__c_time(out, di, uo) is det.
:- pragma c_code(time__c_time(Ret::out, IO0::di, IO::uo),
[will_not_call_mercury],
"{
Ret = (Integer) time(NULL);
update_io(IO0, IO);
}").
%-----------------------------------------------------------------------------%
%:- func time__difftime(time_t, time_t) = int.
time__difftime(T1, T0) = N :-
time__c_difftime(T1, T0, N).
:- pred time__c_difftime(int, int, int).
:- mode time__c_difftime(in, in, out) is det.
:- pragma c_code(time__c_difftime(T1::in, T0::in, N::out),
[will_not_call_mercury],
"{
N = (Integer) difftime((time_t) T1, (time_t) T0);
}").
%-----------------------------------------------------------------------------%
%:- func time__localtime(time_t) = tm.
:- import_module int, exception.
time__localtime(Time) = TM :-
time__c_localtime(Time, Sec, Min, Hrs, WD, YD, Mnt, Yr, N),
( N = 0 ->
DST = yes(standard_time)
; N > 0 ->
DST = yes(daylight_time)
; % N < 0
DST = no
),
TM = tm(Sec, Min, Hrs, WD, YD, Mnt, Yr, DST).
:- pred time__c_localtime(int, int, int, int, int, int, int, int, int).
:- mode time__c_localtime(in, out, out, out, out, out, out, out, out) is det.
:- pragma c_code(time__c_localtime(Time::in, Sec::out, Min::out, Hrs::out,
WD::out, YD::out, Mnt::out,
Yr::out, N::out),
[will_not_call_mercury],
"{
struct tm* p;
time_t t;
t = Time;
p = localtime(&t);
Sec = (Integer) p->tm_sec;
Min = (Integer) p->tm_min;
Hrs = (Integer) p->tm_hour;
Mnt = (Integer) p->tm_mon;
Yr = (Integer) p->tm_year;
WD = (Integer) p->tm_wday;
YD = (Integer) p->tm_yday;
N = (Integer) p->tm_isdst;
}").
%-----------------------------------------------------------------------------%
%:- func time__mktime(tm) = time_t.
time__mktime(TM) = Time :-
TM = tm(Sec, Min, Hrs, WD, YD, Mnt, Yr, M),
( M = yes(DST), DST = daylight_time,
N = 1
; M = yes(DST), DST = standard_time,
N = 0
; M = no,
N = -1
),
time__c_mktime(Sec, Min, Hrs, WD, YD, Mnt, Yr, N, Time).
:- pred time__c_mktime(int, int, int, int, int, int, int, int, int).
:- mode time__c_mktime(in, in, in, in, in, in, in, in, out) is det.
:- pragma c_code(time__c_mktime(Sec::in, Min::in, Hrs::in, WD::in,
YD::in, Mnt::in, Yr::in,
N::in, Time::out),
[will_not_call_mercury],
"{
struct tm t;
t.tm_sec = Sec;
t.tm_min = Min;
t.tm_hour = Hrs;
t.tm_mon = Mnt;
t.tm_year = Yr;
t.tm_wday = WD;
t.tm_yday = YD;
t.tm_isdst = N;
Time = (Integer) mktime(&t);
}").
%-----------------------------------------------------------------------------%
%:- func time__asctime(tm) = string.
time__asctime(TM) = Str :-
TM = tm(Sec, Min, Hrs, WD, YD, Mnt, Yr, M),
( M = yes(DST), DST = daylight_time,
N = 1
; M = yes(DST), DST = standard_time,
N = 0
; M = no,
N = -1
),
time__c_asctime(Sec, Min, Hrs, WD, YD, Mnt, Yr, N, Str).
:- pred time__c_asctime(int, int, int, int, int, int, int, int, string).
:- mode time__c_asctime(in, in, in, in, in, in, in, in, out) is det.
:- pragma c_code(time__c_asctime(Sec::in, Min::in, Hrs::in, WD::in,
YD::in, Mnt::in, Yr::in, N::in, Str::out),
[will_not_call_mercury],
"{
struct tm t;
char* s;
t.tm_sec = Sec;
t.tm_min = Min;
t.tm_hour = Hrs;
t.tm_mon = Mnt;
t.tm_year = Yr;
t.tm_wday = WD;
t.tm_yday = YD;
t.tm_isdst = N;
s = asctime(&t);
MR_make_aligned_string_copy(Str, s);
}").
%-----------------------------------------------------------------------------%
%:- func time__ctime(time_t) = string.
time__ctime(Time) = Str :-
time__c_ctime(Time, Str).
:- pred time__c_ctime(int, string).
:- mode time__c_ctime(in, out) is det.
:- pragma c_code(time__c_ctime(Time::in, Str::out),
[will_not_call_mercury],
"{
char *s;
time_t t;
t = Time;
s = ctime(&t);
MR_make_aligned_string_copy(Str, s);
}").
%-----------------------------------------------------------------------------%
:- end_module time.
%-----------------------------------------------------------------------------%
--
Fergus Henderson <fjh at cs.mu.oz.au> | "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh> | of excellence is a lethal habit"
PGP: finger fjh at 128.250.37.3 | -- the last words of T. S. Garp.
--------------------------------------------------------------------------
mercury-developers mailing list
Post messages to: mercury-developers at cs.mu.oz.au
Administrative Queries: owner-mercury-developers at cs.mu.oz.au
Subscriptions: mercury-developers-request at cs.mu.oz.au
--------------------------------------------------------------------------
More information about the developers
mailing list