Hi,
Have a look at these nearly identical ways to calculate
(decode-universal-time (get-universal-time)):
$ bin/uninstalled-sbcl
This is SBCL 0.8.18.18, an implementation of ANSI Common Lisp.
More information about SBCL is available at <http://www.sbcl.org/>.
SBCL is free software, provided as is, with absolutely no warranty.
It is mostly in the public domain; some portions are provided under
BSD-style licenses. See the CREDITS and COPYING files in the
distribution for more information.
* (machine-type)
"X86-64"
* (decode-universal-time (get-universal-time))
10
44
23
7
1
2005
4
T
0
* (get-universal-time)
3314126650
* (decode-universal-time *)
10
44
23
7
1
2005
4
NIL
-1
*
Note that the last two values of each call to decode-universal-time are
different. (The last result is the correct one.)
I'm still somewhat mystified by the two result being different, but
I do think I understand what causes the wrong answer: a type mismatch.
src/runtime/time.c:
void get_timezone(time_t when, int *secwest, boolean *dst)
^^^^^^^
src/runtime/runtime.h:
/* Too bad ANSI C doesn't define "bool" as C++ does.. */
typedef int boolean;
^^^
src/code/unix.lisp:
(define-alien-routine get-timezone sb!alien:void
(when sb!alien:long :in)
(seconds-west sb!alien:int :out)
(daylight-savings-p sb!alien:boolean :out))
^^^^^^^
src/code/host-alieneval.lisp:
(define-alien-type-translator boolean (&optional (bits sb!vm:n-word-bits))
^^^^^^^^^^^
(make-alien-boolean-type :bits bits :signed nil))
And indeed, changing the sb!alien:boolean declaration in get-timezone
into (sb!alien:boolean 32) seems to fix this. I'm not sure whether that's
the right place to fix it, though. I wouldn't expect any C programmer to
use a long to hold a boolean. An int would be more likely, so in that
light it would be more practical to change the default size of a boolean
in the above definition from n-word-bits into either 32 or
(sb!alien:alien-size sb!alien:int).
On the other hand, from some random internet pages I understand that C99
has a _Bool type (and stdbool.h defines bool to be _Bool, false to be
(_Bool)0 and true to be (_Bool)1). I assume its size is not in the C99
standard, but gcc 3.2 on x86 and gcc 3.3.5 on x86-64 both tell me that
sizeof(bool) is sizeof(_Bool) is 1.
(To make this a bit more fun, gcc 2.95.4 also comes with a stdbool.h,
but this one defines bool as en enumeration type, so sizeof(bool) is 4.)
I still think however that the option of least surprise when dealing
with most current C code is to make sb-alien:boolean default to 32 bits,
so my vote would be for that one.
Vincent.
|