1 /* Copyright (C) 1995,1996,1997,1998,1999,2000,2001, 2003, 2004, 2005, 2006,
2 * 2007, 2008, 2009, 2011, 2013, 2014 Free Software Foundation, Inc.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public License
6 * as published by the Free Software Foundation; either version 3 of
7 * the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 /* _POSIX_C_SOURCE is not defined always, because it causes problems on some
26 - FreeBSD loses all BSD and XOPEN defines.
27 - glibc loses some things like CLK_TCK.
28 - On MINGW it conflicts with the pthread headers.
30 But on HP-UX _POSIX_C_SOURCE is needed, as noted, for gmtime_r.
32 Perhaps a configure test could figure out what _POSIX_C_SOURCE gives and
33 what it takes away, and decide from that whether to use it, instead of
34 hard coding __hpux. */
37 # define _REENTRANT /* ask solaris for gmtime_r prototype */
40 #define _POSIX_C_SOURCE 199506L /* for gmtime_r prototype */
52 #include "libguile/_scm.h"
53 #include "libguile/async.h"
54 #include "libguile/feature.h"
55 #include "libguile/strings.h"
56 #include "libguile/vectors.h"
57 #include "libguile/dynwind.h"
58 #include "libguile/strings.h"
60 #include "libguile/validate.h"
61 #include "libguile/stime.h"
66 #ifdef HAVE_CLOCK_GETTIME
70 #include <sys/types.h>
72 #include <sys/times.h>
74 #ifdef HAVE_SYS_TIMEB_H
75 # include <sys/timeb.h>
78 #if ! HAVE_DECL_STRPTIME
79 extern char *strptime ();
89 #if SCM_SIZEOF_LONG >= 8 && defined HAVE_CLOCK_GETTIME
90 /* Nanoseconds on 64-bit systems with POSIX timers. */
91 #define TIME_UNITS_PER_SECOND 1000000000
93 /* Milliseconds for everyone else. */
94 #define TIME_UNITS_PER_SECOND 1000
97 long scm_c_time_units_per_second
= TIME_UNITS_PER_SECOND
;
100 time_from_seconds_and_nanoseconds (long s
, long ns
)
102 return s
* TIME_UNITS_PER_SECOND
103 + ns
/ (1000000000 / TIME_UNITS_PER_SECOND
);
107 /* A runtime-selectable mechanism to choose a timing mechanism. Really
108 we want to use POSIX timers, but that's not always possible. Notably,
109 the user may have everything she needs at compile-time, but if she's
110 running on an SMP machine without a common clock source, she can't
111 use POSIX CPUTIME clocks. */
112 static long (*get_internal_real_time
) (void);
113 static long (*get_internal_run_time
) (void);
116 #ifdef HAVE_CLOCK_GETTIME
117 struct timespec posix_real_time_base
;
120 get_internal_real_time_posix_timer (void)
123 clock_gettime (CLOCK_REALTIME
, &ts
);
124 return time_from_seconds_and_nanoseconds
125 (ts
.tv_sec
- posix_real_time_base
.tv_sec
,
126 ts
.tv_nsec
- posix_real_time_base
.tv_nsec
);
129 #if defined _POSIX_CPUTIME && defined CLOCK_PROCESS_CPUTIME_ID
130 /* You see, FreeBSD defines _POSIX_CPUTIME but not
131 CLOCK_PROCESS_CPUTIME_ID. */
132 #define HAVE_POSIX_CPUTIME 1
134 struct timespec posix_run_time_base
;
137 get_internal_run_time_posix_timer (void)
140 clock_gettime (CLOCK_PROCESS_CPUTIME_ID
, &ts
);
141 return time_from_seconds_and_nanoseconds
142 (ts
.tv_sec
- posix_run_time_base
.tv_sec
,
143 ts
.tv_nsec
- posix_run_time_base
.tv_nsec
);
145 #endif /* _POSIX_CPUTIME */
146 #endif /* HAVE_CLOCKTIME */
149 #ifdef HAVE_GETTIMEOFDAY
150 struct timeval gettimeofday_real_time_base
;
153 get_internal_real_time_gettimeofday (void)
156 gettimeofday (&tv
, NULL
);
157 return time_from_seconds_and_nanoseconds
158 (tv
.tv_sec
- gettimeofday_real_time_base
.tv_sec
,
159 (tv
.tv_usec
- gettimeofday_real_time_base
.tv_usec
) * 1000);
164 static long ticks_per_second
;
167 get_internal_run_time_times (void)
169 struct tms time_buffer
;
171 return (time_buffer
.tms_utime
+ time_buffer
.tms_stime
)
172 * TIME_UNITS_PER_SECOND
/ ticks_per_second
;
175 static timet fallback_real_time_base
;
177 get_internal_real_time_fallback (void)
179 return time_from_seconds_and_nanoseconds
180 ((long) time (NULL
) - fallback_real_time_base
, 0);
184 SCM_DEFINE (scm_get_internal_real_time
, "get-internal-real-time", 0, 0, 0,
186 "Return the number of time units since the interpreter was\n"
188 #define FUNC_NAME s_scm_get_internal_real_time
190 return scm_from_long (get_internal_real_time ());
195 SCM_DEFINE (scm_times
, "times", 0, 0, 0,
197 "Return an object with information about real and processor\n"
198 "time. The following procedures accept such an object as an\n"
199 "argument and return a selected component:\n"
203 "The current real time, expressed as time units relative to an\n"
206 "The CPU time units used by the calling process.\n"
208 "The CPU time units used by the system on behalf of the calling\n"
211 "The CPU time units used by terminated child processes of the\n"
212 "calling process, whose status has been collected (e.g., using\n"
215 "Similarly, the CPU times units used by the system on behalf of\n"
216 "terminated child processes.\n"
218 #define FUNC_NAME s_scm_times
224 SCM result
= scm_c_make_vector (5, SCM_UNDEFINED
);
229 factor
= scm_quotient (scm_from_long (TIME_UNITS_PER_SECOND
),
230 scm_from_long (ticks_per_second
));
232 SCM_SIMPLE_VECTOR_SET (result
, 0,
233 scm_product (scm_from_long (rv
), factor
));
234 SCM_SIMPLE_VECTOR_SET (result
, 1,
235 scm_product (scm_from_long (t
.tms_utime
), factor
));
236 SCM_SIMPLE_VECTOR_SET (result
, 2,
237 scm_product (scm_from_long (t
.tms_stime
), factor
));
238 SCM_SIMPLE_VECTOR_SET (result
,3,
239 scm_product (scm_from_long (t
.tms_cutime
), factor
));
240 SCM_SIMPLE_VECTOR_SET (result
, 4,
241 scm_product (scm_from_long (t
.tms_cstime
), factor
));
247 scm_c_get_internal_run_time (void)
249 return get_internal_run_time ();
252 SCM_DEFINE (scm_get_internal_run_time
, "get-internal-run-time", 0, 0, 0,
254 "Return the number of time units of processor time used by the\n"
255 "interpreter. Both @emph{system} and @emph{user} time are\n"
256 "included but subprocesses are not.")
257 #define FUNC_NAME s_scm_get_internal_run_time
259 return scm_from_long (scm_c_get_internal_run_time ());
263 /* For reference, note that current-time and gettimeofday both should be
264 protected against setzone/restorezone changes in another thread, since on
265 DOS the system time is normally kept as local time, which means TZ
266 affects the return from current-time and gettimeofday. Not sure if DJGPP
267 etc actually has concurrent multi-threading, but it seems prudent not to
268 make assumptions about this. */
270 SCM_DEFINE (scm_current_time
, "current-time", 0, 0, 0,
272 "Return the number of seconds since 1970-01-01 00:00:00 UTC,\n"
273 "excluding leap seconds.")
274 #define FUNC_NAME s_scm_current_time
278 SCM_CRITICAL_SECTION_START
;
280 SCM_CRITICAL_SECTION_END
;
282 SCM_MISC_ERROR ("current time not available", SCM_EOL
);
283 return scm_from_long (timv
);
287 SCM_DEFINE (scm_gettimeofday
, "gettimeofday", 0, 0, 0,
289 "Return a pair containing the number of seconds and microseconds\n"
290 "since 1970-01-01 00:00:00 UTC, excluding leap seconds. Note:\n"
291 "whether true microsecond resolution is available depends on the\n"
293 #define FUNC_NAME s_scm_gettimeofday
295 #ifdef HAVE_GETTIMEOFDAY
298 if (gettimeofday (&time
, NULL
))
301 return scm_cons (scm_from_long (time
.tv_sec
),
302 scm_from_long (time
.tv_usec
));
304 timet t
= time (NULL
);
308 return scm_cons (scm_from_long ((long)t
), SCM_INUM0
);
314 filltime (struct tm
*bd_time
, int zoff
, const char *zname
)
316 SCM result
= scm_c_make_vector (11, SCM_UNDEFINED
);
318 SCM_SIMPLE_VECTOR_SET (result
,0, scm_from_int (bd_time
->tm_sec
));
319 SCM_SIMPLE_VECTOR_SET (result
,1, scm_from_int (bd_time
->tm_min
));
320 SCM_SIMPLE_VECTOR_SET (result
,2, scm_from_int (bd_time
->tm_hour
));
321 SCM_SIMPLE_VECTOR_SET (result
,3, scm_from_int (bd_time
->tm_mday
));
322 SCM_SIMPLE_VECTOR_SET (result
,4, scm_from_int (bd_time
->tm_mon
));
323 SCM_SIMPLE_VECTOR_SET (result
,5, scm_from_int (bd_time
->tm_year
));
324 SCM_SIMPLE_VECTOR_SET (result
,6, scm_from_int (bd_time
->tm_wday
));
325 SCM_SIMPLE_VECTOR_SET (result
,7, scm_from_int (bd_time
->tm_yday
));
326 SCM_SIMPLE_VECTOR_SET (result
,8, scm_from_int (bd_time
->tm_isdst
));
327 SCM_SIMPLE_VECTOR_SET (result
,9, scm_from_int (zoff
));
328 SCM_SIMPLE_VECTOR_SET (result
,10, (zname
329 ? scm_from_locale_string (zname
)
334 static char tzvar
[3] = "TZ";
336 /* if zone is set, create a temporary environment with only a TZ
337 string. other threads or interrupt handlers shouldn't be allowed
338 to run until the corresponding restorezone is called. hence the use
339 of a static variable for tmpenv is no big deal. */
341 setzone (SCM zone
, int pos
, const char *subr
)
345 if (!SCM_UNBNDP (zone
))
347 static char *tmpenv
[2];
351 zone_len
= scm_to_locale_stringbuf (zone
, NULL
, 0);
352 buf
= scm_malloc (zone_len
+ sizeof (tzvar
) + 1);
354 buf
[sizeof(tzvar
)-1] = '=';
355 scm_to_locale_stringbuf (zone
, buf
+sizeof(tzvar
), zone_len
);
356 buf
[sizeof(tzvar
)+zone_len
] = '\0';
366 restorezone (SCM zone
, char **oldenv
, const char *subr SCM_UNUSED
)
368 if (!SCM_UNBNDP (zone
))
373 /* for the possible benefit of user code linked with libguile. */
379 SCM_DEFINE (scm_localtime
, "localtime", 1, 1, 0,
380 (SCM time
, SCM zone
),
381 "Return an object representing the broken down components of\n"
382 "@var{time}, an integer like the one returned by\n"
383 "@code{current-time}. The time zone for the calculation is\n"
384 "optionally specified by @var{zone} (a string), otherwise the\n"
385 "@code{TZ} environment variable or the system default is used.")
386 #define FUNC_NAME s_scm_localtime
389 struct tm
*ltptr
, lt
, *utc
;
396 itime
= SCM_NUM2LONG (1, time
);
398 /* deferring interupts is essential since a) setzone may install a temporary
399 environment b) localtime uses a static buffer. */
400 SCM_CRITICAL_SECTION_START
;
401 oldenv
= setzone (zone
, SCM_ARG2
, FUNC_NAME
);
402 #ifdef LOCALTIME_CACHE
405 /* POSIX says localtime sets errno, but C99 doesn't say that.
406 Give a sensible default value in case localtime doesn't set it. */
408 ltptr
= localtime (&itime
);
414 /* copy zone name before calling gmtime or restoring zone. */
415 #if defined (HAVE_TM_ZONE)
416 ptr
= ltptr
->tm_zone
;
417 #elif defined (HAVE_TZNAME)
418 ptr
= tzname
[ (ltptr
->tm_isdst
== 1) ? 1 : 0 ];
422 zname
= scm_malloc (strlen (ptr
) + 1);
425 /* the struct is copied in case localtime and gmtime share a buffer. */
428 /* POSIX says gmtime sets errno, but C99 doesn't say that.
429 Give a sensible default value in case gmtime doesn't set it. */
431 utc
= gmtime (&itime
);
434 restorezone (zone
, oldenv
, FUNC_NAME
);
435 /* delayed until zone has been restored. */
437 if (utc
== NULL
|| ltptr
== NULL
)
440 /* calculate timezone offset in seconds west of UTC. */
441 zoff
= (utc
->tm_hour
- lt
.tm_hour
) * 3600 + (utc
->tm_min
- lt
.tm_min
) * 60
442 + utc
->tm_sec
- lt
.tm_sec
;
443 if (utc
->tm_year
< lt
.tm_year
)
444 zoff
-= 24 * 60 * 60;
445 else if (utc
->tm_year
> lt
.tm_year
)
446 zoff
+= 24 * 60 * 60;
447 else if (utc
->tm_yday
< lt
.tm_yday
)
448 zoff
-= 24 * 60 * 60;
449 else if (utc
->tm_yday
> lt
.tm_yday
)
450 zoff
+= 24 * 60 * 60;
452 result
= filltime (<
, zoff
, zname
);
453 SCM_CRITICAL_SECTION_END
;
460 /* tm_zone is normally a pointer, not an array within struct tm, so we might
461 have to worry about the lifespan of what it points to. The posix specs
462 don't seem to say anything about this, let's assume here that tm_zone
463 will be a constant and therefore no protection or anything is needed
464 until we copy it in filltime(). */
466 SCM_DEFINE (scm_gmtime
, "gmtime", 1, 0, 0,
468 "Return an object representing the broken down components of\n"
469 "@var{time}, an integer like the one returned by\n"
470 "@code{current-time}. The values are calculated for UTC.")
471 #define FUNC_NAME s_scm_gmtime
474 struct tm bd_buf
, *bd_time
;
477 itime
= SCM_NUM2LONG (1, time
);
479 /* POSIX says gmtime sets errno, but C99 doesn't say that.
480 Give a sensible default value in case gmtime doesn't set it. */
484 bd_time
= gmtime_r (&itime
, &bd_buf
);
486 SCM_CRITICAL_SECTION_START
;
487 bd_time
= gmtime (&itime
);
490 SCM_CRITICAL_SECTION_END
;
495 #if HAVE_STRUCT_TM_TM_ZONE
496 zname
= bd_buf
.tm_zone
;
500 return filltime (&bd_buf
, 0, zname
);
504 /* copy time components from a Scheme object to a struct tm. */
506 bdtime2c (SCM sbd_time
, struct tm
*lt
, int pos
, const char *subr
)
508 SCM_ASSERT (scm_is_vector (sbd_time
)
509 && SCM_SIMPLE_VECTOR_LENGTH (sbd_time
) == 11,
510 sbd_time
, pos
, subr
);
512 lt
->tm_sec
= scm_to_int (SCM_SIMPLE_VECTOR_REF (sbd_time
, 0));
513 lt
->tm_min
= scm_to_int (SCM_SIMPLE_VECTOR_REF (sbd_time
, 1));
514 lt
->tm_hour
= scm_to_int (SCM_SIMPLE_VECTOR_REF (sbd_time
, 2));
515 lt
->tm_mday
= scm_to_int (SCM_SIMPLE_VECTOR_REF (sbd_time
, 3));
516 lt
->tm_mon
= scm_to_int (SCM_SIMPLE_VECTOR_REF (sbd_time
, 4));
517 lt
->tm_year
= scm_to_int (SCM_SIMPLE_VECTOR_REF (sbd_time
, 5));
518 lt
->tm_wday
= scm_to_int (SCM_SIMPLE_VECTOR_REF (sbd_time
, 6));
519 lt
->tm_yday
= scm_to_int (SCM_SIMPLE_VECTOR_REF (sbd_time
, 7));
520 lt
->tm_isdst
= scm_to_int (SCM_SIMPLE_VECTOR_REF (sbd_time
, 8));
521 #if HAVE_STRUCT_TM_TM_GMTOFF
522 lt
->tm_gmtoff
= - scm_to_int (SCM_SIMPLE_VECTOR_REF (sbd_time
, 9));
525 if (scm_is_false (SCM_SIMPLE_VECTOR_REF (sbd_time
, 10)))
528 lt
->tm_zone
= scm_to_locale_string (SCM_SIMPLE_VECTOR_REF (sbd_time
, 10));
532 SCM_DEFINE (scm_mktime
, "mktime", 1, 1, 0,
533 (SCM sbd_time
, SCM zone
),
534 "@var{sbd_time} is an object representing broken down time and\n"
535 "@code{zone} is an optional time zone specifier (otherwise the\n"
536 "TZ environment variable or the system default is used).\n"
538 "Returns a pair: the car is a corresponding integer time value\n"
539 "like that returned by @code{current-time}; the cdr is a broken\n"
540 "down time object, similar to as @var{sbd_time} but with\n"
541 "normalized values.")
542 #define FUNC_NAME s_scm_mktime
552 scm_dynwind_begin (0);
554 bdtime2c (sbd_time
, <
, SCM_ARG1
, FUNC_NAME
);
555 #if HAVE_STRUCT_TM_TM_ZONE
556 scm_dynwind_free ((char *)lt
.tm_zone
);
559 scm_dynwind_critical_section (SCM_BOOL_F
);
561 oldenv
= setzone (zone
, SCM_ARG2
, FUNC_NAME
);
562 #ifdef LOCALTIME_CACHE
565 itime
= mktime (<
);
566 /* POSIX doesn't say mktime sets errno, and on glibc 2.3.2 for instance it
567 doesn't. Force a sensible value for our error message. */
574 /* copy zone name before calling gmtime or restoring the zone. */
575 #if defined (HAVE_TM_ZONE)
577 #elif defined (HAVE_TZNAME)
578 ptr
= tzname
[ (lt
.tm_isdst
== 1) ? 1 : 0 ];
582 zname
= scm_malloc (strlen (ptr
) + 1);
586 /* get timezone offset in seconds west of UTC. */
587 /* POSIX says gmtime sets errno, but C99 doesn't say that.
588 Give a sensible default value in case gmtime doesn't set it. */
590 utc
= gmtime (&itime
);
594 restorezone (zone
, oldenv
, FUNC_NAME
);
595 /* delayed until zone has been restored. */
597 if (utc
== NULL
|| itime
== -1)
600 zoff
= (utc
->tm_hour
- lt
.tm_hour
) * 3600 + (utc
->tm_min
- lt
.tm_min
) * 60
601 + utc
->tm_sec
- lt
.tm_sec
;
602 if (utc
->tm_year
< lt
.tm_year
)
603 zoff
-= 24 * 60 * 60;
604 else if (utc
->tm_year
> lt
.tm_year
)
605 zoff
+= 24 * 60 * 60;
606 else if (utc
->tm_yday
< lt
.tm_yday
)
607 zoff
-= 24 * 60 * 60;
608 else if (utc
->tm_yday
> lt
.tm_yday
)
609 zoff
+= 24 * 60 * 60;
611 result
= scm_cons (scm_from_long (itime
),
612 filltime (<
, zoff
, zname
));
621 SCM_DEFINE (scm_tzset
, "tzset", 0, 0, 0,
623 "Initialize the timezone from the TZ environment variable\n"
624 "or the system default. It's not usually necessary to call this procedure\n"
625 "since it's done automatically by other procedures that depend on the\n"
627 #define FUNC_NAME s_scm_tzset
630 return SCM_UNSPECIFIED
;
633 #endif /* HAVE_TZSET */
635 SCM_DEFINE (scm_strftime
, "strftime", 2, 0, 0,
636 (SCM format
, SCM stime
),
637 "Return a string which is broken-down time structure @var{stime}\n"
638 "formatted according to the given @var{format} string.\n"
640 "@var{format} contains field specifications introduced by a\n"
641 "@samp{%} character. See @ref{Formatting Calendar Time,,, libc,\n"
642 "The GNU C Library Reference Manual}, or @samp{man 3 strftime},\n"
643 "for the available formatting.\n"
646 "(strftime \"%c\" (localtime (current-time)))\n"
647 "@result{} \"Mon Mar 11 20:17:43 2002\"\n"
650 "If @code{setlocale} has been called (@pxref{Locales}), month\n"
651 "and day names are from the current locale and in the locale\n"
653 #define FUNC_NAME s_scm_strftime
664 SCM_VALIDATE_STRING (1, format
);
665 bdtime2c (stime
, &t
, SCM_ARG2
, FUNC_NAME
);
667 /* Convert string to UTF-8 so that non-ASCII characters in the
668 format are passed through unchanged. */
669 fmt
= scm_to_utf8_stringn (format
, &len
);
671 /* Ugly hack: strftime can return 0 if its buffer is too small,
672 but some valid time strings (e.g. "%p") can sometimes produce
673 a zero-byte output string! Workaround is to prepend a junk
674 character to the format string, so that valid returns are always
676 myfmt
= scm_malloc (len
+2);
677 *myfmt
= (scm_t_uint8
) 'x';
678 strncpy (myfmt
+ 1, fmt
, len
);
680 scm_remember_upto_here_1 (format
);
683 tbuf
= scm_malloc (size
);
685 #if !defined (HAVE_TM_ZONE)
686 /* it seems the only way to tell non-GNU versions of strftime what
687 zone to use (for the %Z format) is to set TZ in the
688 environment. interrupts and thread switching must be deferred
689 until TZ is restored. */
690 char **oldenv
= NULL
;
691 SCM zone_spec
= SCM_SIMPLE_VECTOR_REF (stime
, 10);
694 if (scm_is_true (zone_spec
) && scm_c_string_length (zone_spec
) > 0)
696 /* it's not required that the TZ setting be correct, just that
697 it has the right name. so try something like TZ=EST0.
698 using only TZ=EST would be simpler but it doesn't work on
699 some OSs, e.g., Solaris. */
701 scm_string_append (scm_list_2 (zone_spec
,
702 scm_from_locale_string ("0")));
705 SCM_CRITICAL_SECTION_START
;
706 oldenv
= setzone (zone
, SCM_ARG2
, FUNC_NAME
);
710 #ifdef LOCALTIME_CACHE
714 /* Use `nstrftime ()' from Gnulib, which supports all GNU extensions
715 supported by glibc. */
716 while ((len
= nstrftime (tbuf
, size
, myfmt
, &t
, 0, 0)) == 0)
720 tbuf
= scm_malloc (size
);
723 #if !defined (HAVE_TM_ZONE)
726 restorezone (zone_spec
, oldenv
, FUNC_NAME
);
727 SCM_CRITICAL_SECTION_END
;
732 result
= scm_from_utf8_string (tbuf
+ 1);
735 #if HAVE_STRUCT_TM_TM_ZONE
736 free ((char *) t
.tm_zone
);
743 SCM_DEFINE (scm_strptime
, "strptime", 2, 0, 0,
744 (SCM format
, SCM string
),
745 "Performs the reverse action to @code{strftime}, parsing\n"
746 "@var{string} according to the specification supplied in\n"
747 "@var{format}. The interpretation of month and day names is\n"
748 "dependent on the current locale. The value returned is a pair.\n"
749 "The car has an object with time components\n"
750 "in the form returned by @code{localtime} or @code{gmtime},\n"
751 "but the time zone components\n"
752 "are not usefully set.\n"
753 "The cdr reports the number of characters from @var{string}\n"
754 "which were used for the conversion.")
755 #define FUNC_NAME s_scm_strptime
758 char *fmt
, *str
, *rest
;
762 SCM_VALIDATE_STRING (1, format
);
763 SCM_VALIDATE_STRING (2, string
);
765 /* Convert strings to UTF-8 so that non-ASCII characters are passed
766 through unchanged. */
767 fmt
= scm_to_utf8_string (format
);
768 str
= scm_to_utf8_string (string
);
770 /* initialize the struct tm */
771 #define tm_init(field) t.field = 0
780 #if HAVE_STRUCT_TM_TM_GMTOFF
785 /* GNU glibc strptime() "%s" is affected by the current timezone, since it
786 reads a UTC time_t value and converts with localtime_r() to set the tm
787 fields, hence the use of SCM_CRITICAL_SECTION_START. */
789 SCM_CRITICAL_SECTION_START
;
790 rest
= strptime (str
, fmt
, &t
);
791 SCM_CRITICAL_SECTION_END
;
794 /* POSIX doesn't say strptime sets errno, and on glibc 2.3.2 for
795 instance it doesn't. Force a sensible value for our error
798 scm_remember_upto_here_2 (format
, string
);
804 /* tm_gmtoff is set by GNU glibc strptime "%s", so capture it when
806 #if HAVE_STRUCT_TM_TM_GMTOFF
807 zoff
= - t
.tm_gmtoff
; /* seconds west, not east */
812 /* Compute the number of UTF-8 characters. */
813 used_len
= u8_strnlen ((scm_t_uint8
*) str
, rest
-str
);
814 scm_remember_upto_here_2 (format
, string
);
818 return scm_cons (filltime (&t
, zoff
, NULL
),
819 scm_from_signed_integer (used_len
));
822 #endif /* HAVE_STRPTIME */
827 scm_c_define ("internal-time-units-per-second",
828 scm_from_long (SCM_TIME_UNITS_PER_SECOND
));
830 /* Init POSIX timers, and see if we can use them. */
831 #ifdef HAVE_CLOCK_GETTIME
832 if (clock_gettime (CLOCK_REALTIME
, &posix_real_time_base
) == 0)
833 get_internal_real_time
= get_internal_real_time_posix_timer
;
835 #ifdef HAVE_POSIX_CPUTIME
839 /* Only use the _POSIX_CPUTIME clock if it's going to work across
841 if (clock_getcpuclockid (0, &dummy
) == 0 &&
842 clock_gettime (CLOCK_PROCESS_CPUTIME_ID
, &posix_run_time_base
) == 0)
843 get_internal_run_time
= get_internal_run_time_posix_timer
;
847 #endif /* HAVE_POSIX_CPUTIME */
848 #endif /* HAVE_CLOCKTIME */
850 /* If needed, init and use gettimeofday timer. */
851 #ifdef HAVE_GETTIMEOFDAY
852 if (!get_internal_real_time
853 && gettimeofday (&gettimeofday_real_time_base
, NULL
) == 0)
854 get_internal_real_time
= get_internal_real_time_gettimeofday
;
857 /* Init ticks_per_second for scm_times, and use times(2)-based
858 run-time timer if needed. */
860 ticks_per_second
= sysconf (_SC_CLK_TCK
);
862 ticks_per_second
= CLK_TCK
;
864 if (!get_internal_run_time
)
865 get_internal_run_time
= get_internal_run_time_times
;
867 if (!get_internal_real_time
)
868 /* No POSIX timers, gettimeofday doesn't work... badness! */
870 fallback_real_time_base
= time (NULL
);
871 get_internal_real_time
= get_internal_real_time_fallback
;
874 scm_add_feature ("current-time");
875 #include "libguile/stime.x"