This source file includes following definitions.
- trillion_factor
- make_timeval
- tm_gmtoff
- tm_diff
- emacs_localtime_rz
- invalid_time_zone_specification
- xtzfree
- tzlookup
- init_timefns
- time_overflow
- time_error
- invalid_hz
- hi_time
- lo_time
- decode_float_time
- ticks_hz_list4
- mpz_set_time
- timespec_mpz
- timespec_ticks
- lisp_time_hz_ticks
- lisp_time_seconds
- make_lisp_time
- timespec_to_lisp
- frac_to_double
- decode_ticks_hz
- decode_time_components
- decode_lisp_time
- float_time
- mpz_time
- lisp_to_timespec
- list4_to_timespec
- lisp_time_struct
- lisp_time_argument
- lisp_seconds_argument
- lispint_arith
- time_arith
- time_cmp
- DEFUN
- emacs_nmemftime
- format_time_string
- check_tm_member
- DEFUN
- DEFUN
- DEFUN
- emacs_getenv_TZ
- emacs_setenv_TZ
- syms_of_timefns_for_pdumper
- syms_of_timefns
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 #include <config.h>
21
22
23 #if 10 <= __GNUC__
24 # pragma GCC diagnostic ignored "-Wanalyzer-null-dereference"
25 #endif
26
27 #include "systime.h"
28
29 #include "blockinput.h"
30 #include "bignum.h"
31 #include "coding.h"
32 #include "lisp.h"
33 #include "pdumper.h"
34
35 #include <strftime.h>
36
37 #include <errno.h>
38 #include <limits.h>
39 #include <math.h>
40 #include <stdio.h>
41 #include <stdlib.h>
42
43 #ifdef WINDOWSNT
44 extern clock_t sys_clock (void);
45 #endif
46
47 #ifdef HAVE_TIMEZONE_T
48 # include <sys/param.h>
49 # if defined __NetBSD_Version__ && __NetBSD_Version__ < 700000000
50 # define HAVE_TZALLOC_BUG true
51 # endif
52 #endif
53 #ifndef HAVE_TZALLOC_BUG
54 # define HAVE_TZALLOC_BUG false
55 #endif
56
57 enum { TM_YEAR_BASE = 1900 };
58
59 #ifndef HAVE_TM_GMTOFF
60 # define HAVE_TM_GMTOFF false
61 #endif
62
63 #ifndef TIME_T_MIN
64 # define TIME_T_MIN TYPE_MINIMUM (time_t)
65 #endif
66 #ifndef TIME_T_MAX
67 # define TIME_T_MAX TYPE_MAXIMUM (time_t)
68 #endif
69
70
71
72 #ifndef FASTER_TIMEFNS
73 # define FASTER_TIMEFNS 1
74 #endif
75
76
77
78
79 #ifndef CURRENT_TIME_LIST
80 enum { CURRENT_TIME_LIST = true };
81 #endif
82
83 #if FIXNUM_OVERFLOW_P (1000000000)
84 static Lisp_Object timespec_hz;
85 #else
86 # define timespec_hz make_fixnum (TIMESPEC_HZ)
87 #endif
88
89 #define TRILLION 1000000000000
90 #if FIXNUM_OVERFLOW_P (TRILLION)
91 static Lisp_Object trillion;
92 # define ztrillion (*xbignum_val (trillion))
93 #else
94 # define trillion make_fixnum (TRILLION)
95 # if ULONG_MAX < TRILLION || !FASTER_TIMEFNS
96 mpz_t ztrillion;
97 # endif
98 #endif
99
100
101 static bool
102 trillion_factor (Lisp_Object hz)
103 {
104 if (FASTER_TIMEFNS)
105 {
106 if (FIXNUMP (hz))
107 return TRILLION % XFIXNUM (hz) == 0;
108 if (!FIXNUM_OVERFLOW_P (TRILLION))
109 return false;
110 }
111 verify (TRILLION <= INTMAX_MAX);
112 intmax_t ihz;
113 return integer_to_intmax (hz, &ihz) && TRILLION % ihz == 0;
114 }
115
116
117
118
119 struct timeval
120 make_timeval (struct timespec t)
121 {
122 struct timeval tv;
123 tv.tv_sec = t.tv_sec;
124 tv.tv_usec = t.tv_nsec / 1000;
125
126 if (t.tv_nsec % 1000 != 0)
127 {
128 if (tv.tv_usec < 999999)
129 tv.tv_usec++;
130 else if (tv.tv_sec < TIME_T_MAX)
131 {
132 tv.tv_sec++;
133 tv.tv_usec = 0;
134 }
135 }
136
137 return tv;
138 }
139
140
141 static long int
142 tm_gmtoff (struct tm *a)
143 {
144 #if HAVE_TM_GMTOFF
145 return a->tm_gmtoff;
146 #else
147 return 0;
148 #endif
149 }
150
151
152
153 static int
154 tm_diff (struct tm *a, struct tm *b)
155 {
156
157
158
159 int a4 = (a->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (a->tm_year & 3);
160 int b4 = (b->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (b->tm_year & 3);
161 int a100 = a4 / 25 - (a4 % 25 < 0);
162 int b100 = b4 / 25 - (b4 % 25 < 0);
163 int a400 = a100 >> 2;
164 int b400 = b100 >> 2;
165 int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
166 int years = a->tm_year - b->tm_year;
167 int days = (365 * years + intervening_leap_days
168 + (a->tm_yday - b->tm_yday));
169 return (60 * (60 * (24 * days + (a->tm_hour - b->tm_hour))
170 + (a->tm_min - b->tm_min))
171 + (a->tm_sec - b->tm_sec));
172 }
173
174 enum { tzeqlen = sizeof "TZ=" - 1 };
175
176
177 static timezone_t local_tz;
178 static timezone_t const utc_tz = 0;
179
180 static struct tm *
181 emacs_localtime_rz (timezone_t tz, time_t const *t, struct tm *tm)
182 {
183 #ifdef WINDOWSNT
184
185
186
187
188
189
190 tzset ();
191 #endif
192 tm = localtime_rz (tz, t, tm);
193 if (!tm && errno == ENOMEM)
194 memory_full (SIZE_MAX);
195 return tm;
196 }
197
198 static AVOID
199 invalid_time_zone_specification (Lisp_Object zone)
200 {
201 xsignal2 (Qerror, build_string ("Invalid time zone specification"), zone);
202 }
203
204
205
206 static void
207 xtzfree (timezone_t tz)
208 {
209 if (tz != local_tz)
210 tzfree (tz);
211 }
212
213
214
215
216
217 static timezone_t
218 tzlookup (Lisp_Object zone, bool settz)
219 {
220 static char const tzbuf_format[] = "<%+.*"pI"d>%s%"pI"d:%02d:%02d";
221 char const *trailing_tzbuf_format = tzbuf_format + sizeof "<%+.*"pI"d" - 1;
222 char tzbuf[sizeof tzbuf_format + 2 * INT_STRLEN_BOUND (EMACS_INT)];
223 char const *zone_string;
224 timezone_t new_tz;
225
226 if (NILP (zone))
227 return local_tz;
228 else if (BASE_EQ (zone, make_fixnum (0)) || BASE2_EQ (zone, Qt))
229 {
230 zone_string = "UTC0";
231 new_tz = utc_tz;
232 }
233 else
234 {
235 bool plain_integer = FIXNUMP (zone);
236
237 if (BASE2_EQ (zone, Qwall))
238 zone_string = 0;
239 else if (STRINGP (zone))
240 zone_string = SSDATA (ENCODE_SYSTEM (zone));
241 else if (plain_integer || (CONSP (zone) && FIXNUMP (XCAR (zone))
242 && CONSP (XCDR (zone))))
243 {
244 Lisp_Object abbr UNINIT;
245 if (!plain_integer)
246 {
247 abbr = XCAR (XCDR (zone));
248 zone = XCAR (zone);
249 }
250
251 EMACS_INT abszone = eabs (XFIXNUM (zone)), hour = abszone / (60 * 60);
252 int hour_remainder = abszone % (60 * 60);
253 int min = hour_remainder / 60, sec = hour_remainder % 60;
254
255 if (plain_integer)
256 {
257 int prec = 2;
258 EMACS_INT numzone = hour;
259 if (hour_remainder != 0)
260 {
261 prec += 2, numzone = 100 * numzone + min;
262 if (sec != 0)
263 prec += 2, numzone = 100 * numzone + sec;
264 }
265 sprintf (tzbuf, tzbuf_format, prec,
266 XFIXNUM (zone) < 0 ? -numzone : numzone,
267 &"-"[XFIXNUM (zone) < 0], hour, min, sec);
268 zone_string = tzbuf;
269 }
270 else
271 {
272 AUTO_STRING (leading, "<");
273 AUTO_STRING_WITH_LEN (trailing, tzbuf,
274 sprintf (tzbuf, trailing_tzbuf_format,
275 &"-"[XFIXNUM (zone) < 0],
276 hour, min, sec));
277 zone_string = SSDATA (concat3 (leading, ENCODE_SYSTEM (abbr),
278 trailing));
279 }
280 }
281 else
282 invalid_time_zone_specification (zone);
283
284 new_tz = tzalloc (zone_string);
285
286 if (HAVE_TZALLOC_BUG && !new_tz && errno != ENOMEM && plain_integer
287 && XFIXNUM (zone) % (60 * 60) == 0)
288 {
289
290
291 sprintf (tzbuf, "Etc/GMT%+"pI"d", - (XFIXNUM (zone) / (60 * 60)));
292 new_tz = tzalloc (zone_string);
293 }
294
295 if (!new_tz)
296 {
297 if (errno == ENOMEM)
298 memory_full (SIZE_MAX);
299 invalid_time_zone_specification (zone);
300 }
301 }
302
303 if (settz)
304 {
305 block_input ();
306 emacs_setenv_TZ (zone_string);
307 tzset ();
308 timezone_t old_tz = local_tz;
309 local_tz = new_tz;
310 tzfree (old_tz);
311 unblock_input ();
312 }
313
314 return new_tz;
315 }
316
317 void
318 init_timefns (void)
319 {
320 #ifdef HAVE_UNEXEC
321
322
323 static char dump_tz_string[] = "TZ=UtC0";
324
325
326
327 if (will_dump_with_unexec_p ())
328 {
329 xputenv (dump_tz_string);
330 tzset ();
331 return;
332 }
333 #endif
334
335 char *tz = getenv ("TZ");
336
337 #ifdef HAVE_UNEXEC
338
339
340
341
342
343 if (tz && strcmp (tz, &dump_tz_string[tzeqlen]) == 0)
344 {
345 ++*tz;
346 tzset ();
347 --*tz;
348 }
349 #endif
350
351
352
353 tzlookup (tz ? build_string (tz) : Qwall, true);
354 }
355
356
357 static AVOID
358 time_overflow (void)
359 {
360 error ("Specified time is not representable");
361 }
362
363 static AVOID
364 time_error (int err)
365 {
366 switch (err)
367 {
368 case ENOMEM: memory_full (SIZE_MAX);
369 case EOVERFLOW: time_overflow ();
370 default: error ("Invalid time specification");
371 }
372 }
373
374 static AVOID
375 invalid_hz (Lisp_Object hz)
376 {
377 xsignal2 (Qerror, build_string ("Invalid time frequency"), hz);
378 }
379
380
381 static Lisp_Object
382 hi_time (time_t t)
383 {
384 return INT_TO_INTEGER (t >> LO_TIME_BITS);
385 }
386
387
388 static Lisp_Object
389 lo_time (time_t t)
390 {
391 return make_fixnum (t & ((1 << LO_TIME_BITS) - 1));
392 }
393
394
395
396
397 enum { flt_radix_power_size = DBL_MANT_DIG - DBL_MIN_EXP + 1 };
398
399
400
401 static Lisp_Object flt_radix_power;
402
403
404
405 static void
406 decode_float_time (double t, struct lisp_time *result)
407 {
408 Lisp_Object ticks, hz;
409 if (t == 0)
410 {
411 ticks = make_fixnum (0);
412 hz = make_fixnum (1);
413 }
414 else
415 {
416 int scale = double_integer_scale (t);
417
418
419
420
421 eassume (scale < flt_radix_power_size);
422
423 if (scale < 0)
424 {
425
426
427
428
429
430
431 scale = 0;
432 }
433
434
435
436
437 double scaled = scalbn (t, scale);
438 eassert (trunc (scaled) == scaled);
439 ticks = double_to_integer (scaled);
440 hz = AREF (flt_radix_power, scale);
441 if (NILP (hz))
442 {
443 mpz_ui_pow_ui (mpz[0], FLT_RADIX, scale);
444 hz = make_integer_mpz ();
445 ASET (flt_radix_power, scale, hz);
446 }
447 }
448 result->ticks = ticks;
449 result->hz = hz;
450 }
451
452
453
454 static Lisp_Object
455 ticks_hz_list4 (Lisp_Object ticks, Lisp_Object hz)
456 {
457
458 mpz_t const *zticks = bignum_integer (&mpz[0], ticks);
459 #if FASTER_TIMEFNS && TRILLION <= ULONG_MAX
460 mpz_mul_ui (mpz[0], *zticks, TRILLION);
461 #else
462 mpz_mul (mpz[0], *zticks, ztrillion);
463 #endif
464 mpz_fdiv_q (mpz[0], mpz[0], *bignum_integer (&mpz[1], hz));
465
466
467
468 #if FASTER_TIMEFNS && TRILLION <= ULONG_MAX
469 unsigned long int fullps = mpz_fdiv_q_ui (mpz[0], mpz[0], TRILLION);
470 int us = fullps / 1000000;
471 int ps = fullps % 1000000;
472 #else
473 mpz_fdiv_qr (mpz[0], mpz[1], mpz[0], ztrillion);
474 int ps = mpz_fdiv_q_ui (mpz[1], mpz[1], 1000000);
475 int us = mpz_get_ui (mpz[1]);
476 #endif
477
478
479 unsigned long ulo = mpz_get_ui (mpz[0]);
480 if (mpz_sgn (mpz[0]) < 0)
481 ulo = -ulo;
482 int lo = ulo & ((1 << LO_TIME_BITS) - 1);
483 mpz_fdiv_q_2exp (mpz[0], mpz[0], LO_TIME_BITS);
484
485 return list4 (make_integer_mpz (), make_fixnum (lo),
486 make_fixnum (us), make_fixnum (ps));
487 }
488
489
490 static void
491 mpz_set_time (mpz_t rop, time_t t)
492 {
493 if (EXPR_SIGNED (t))
494 mpz_set_intmax (rop, t);
495 else
496 mpz_set_uintmax (rop, t);
497 }
498
499
500
501 static void
502 timespec_mpz (struct timespec t)
503 {
504
505 mpz_set_ui (mpz[0], t.tv_nsec);
506 mpz_set_time (mpz[1], t.tv_sec);
507 mpz_addmul_ui (mpz[0], mpz[1], TIMESPEC_HZ);
508 }
509
510
511 static Lisp_Object
512 timespec_ticks (struct timespec t)
513 {
514
515 intmax_t accum;
516 if (FASTER_TIMEFNS
517 && !INT_MULTIPLY_WRAPV (t.tv_sec, TIMESPEC_HZ, &accum)
518 && !INT_ADD_WRAPV (t.tv_nsec, accum, &accum))
519 return make_int (accum);
520
521
522 timespec_mpz (t);
523 return make_integer_mpz ();
524 }
525
526
527
528 static Lisp_Object
529 lisp_time_hz_ticks (struct lisp_time t, Lisp_Object hz)
530 {
531
532
533
534 if (FASTER_TIMEFNS && BASE_EQ (t.hz, hz))
535 return t.ticks;
536
537
538 if (FIXNUMP (hz))
539 {
540 if (XFIXNUM (hz) <= 0)
541 invalid_hz (hz);
542
543
544 intmax_t ticks;
545 if (FASTER_TIMEFNS && FIXNUMP (t.ticks) && FIXNUMP (t.hz)
546 && !INT_MULTIPLY_WRAPV (XFIXNUM (t.ticks), XFIXNUM (hz), &ticks))
547 return make_int (ticks / XFIXNUM (t.hz)
548 - (ticks % XFIXNUM (t.hz) < 0));
549 }
550 else if (! (BIGNUMP (hz) && 0 < mpz_sgn (*xbignum_val (hz))))
551 invalid_hz (hz);
552
553
554 mpz_mul (mpz[0],
555 *bignum_integer (&mpz[0], t.ticks),
556 *bignum_integer (&mpz[1], hz));
557 mpz_fdiv_q (mpz[0], mpz[0], *bignum_integer (&mpz[1], t.hz));
558 return make_integer_mpz ();
559 }
560
561
562 static Lisp_Object
563 lisp_time_seconds (struct lisp_time t)
564 {
565
566
567 if (!FASTER_TIMEFNS)
568 return lisp_time_hz_ticks (t, make_fixnum (1));
569
570
571 if (FIXNUMP (t.ticks) && FIXNUMP (t.hz))
572 return make_fixnum (XFIXNUM (t.ticks) / XFIXNUM (t.hz)
573 - (XFIXNUM (t.ticks) % XFIXNUM (t.hz) < 0));
574
575
576 mpz_fdiv_q (mpz[0],
577 *bignum_integer (&mpz[0], t.ticks),
578 *bignum_integer (&mpz[1], t.hz));
579 return make_integer_mpz ();
580 }
581
582
583 Lisp_Object
584 make_lisp_time (struct timespec t)
585 {
586 if (current_time_list)
587 {
588 time_t s = t.tv_sec;
589 int ns = t.tv_nsec;
590 return list4 (hi_time (s), lo_time (s),
591 make_fixnum (ns / 1000), make_fixnum (ns % 1000 * 1000));
592 }
593 else
594 return timespec_to_lisp (t);
595 }
596
597
598 Lisp_Object
599 timespec_to_lisp (struct timespec t)
600 {
601 return Fcons (timespec_ticks (t), timespec_hz);
602 }
603
604
605
606 static double
607 frac_to_double (Lisp_Object numerator, Lisp_Object denominator)
608 {
609 intmax_t intmax_numerator, intmax_denominator;
610 if (FASTER_TIMEFNS
611 && integer_to_intmax (numerator, &intmax_numerator)
612 && integer_to_intmax (denominator, &intmax_denominator)
613 && intmax_numerator % intmax_denominator == 0)
614 return intmax_numerator / intmax_denominator;
615
616
617 mpz_t const *n = bignum_integer (&mpz[0], numerator);
618 mpz_t const *d = bignum_integer (&mpz[1], denominator);
619 ptrdiff_t ndig = mpz_sizeinbase (*n, FLT_RADIX);
620 ptrdiff_t ddig = mpz_sizeinbase (*d, FLT_RADIX);
621
622
623
624
625
626
627 ptrdiff_t scale = ddig - ndig + DBL_MANT_DIG;
628 if (scale < 0)
629 {
630 mpz_mul_2exp (mpz[1], *d, - (scale * LOG2_FLT_RADIX));
631 d = &mpz[1];
632 }
633 else
634 {
635
636 scale = min (scale, flt_radix_power_size - 1);
637
638 mpz_mul_2exp (mpz[0], *n, scale * LOG2_FLT_RADIX);
639 n = &mpz[0];
640 }
641
642 mpz_t *q = &mpz[2];
643 mpz_t *r = &mpz[3];
644 mpz_tdiv_qr (*q, *r, *n, *d);
645
646
647
648 int incr;
649
650
651
652
653
654
655 if (mpz_sizeinbase (*q, FLT_RADIX) <= DBL_MANT_DIG)
656 {
657
658
659
660
661 mpz_mul_2exp (*r, *r, 1);
662 int cmp = mpz_cmpabs (*r, *d);
663 incr = cmp > 0 || (cmp == 0 && (FASTER_TIMEFNS && FLT_RADIX == 2
664 ? mpz_odd_p (*q)
665 : mpz_tdiv_ui (*q, FLT_RADIX) & 1));
666 }
667 else
668 {
669
670
671 int lo_2digits = mpz_tdiv_ui (*q, FLT_RADIX * FLT_RADIX);
672 eassume (0 <= lo_2digits && lo_2digits < FLT_RADIX * FLT_RADIX);
673 int lo_digit = lo_2digits % FLT_RADIX;
674 incr = ((lo_digit > FLT_RADIX / 2
675 || (lo_digit == FLT_RADIX / 2 && FLT_RADIX % 2 == 0
676 && ((lo_2digits / FLT_RADIX) & 1
677 || mpz_sgn (*r) != 0)))
678 ? FLT_RADIX : 0);
679 }
680
681
682 if (!FASTER_TIMEFNS || incr != 0)
683 (mpz_sgn (*n) < 0 ? mpz_sub_ui : mpz_add_ui) (*q, *q, incr);
684
685
686 return scalbn (mpz_get_d (*q), -scale);
687 }
688
689
690
691
692
693
694
695
696
697 static int
698 decode_ticks_hz (Lisp_Object ticks, Lisp_Object hz,
699 struct lisp_time *result, double *dresult)
700 {
701 if (result)
702 {
703 result->ticks = ticks;
704 result->hz = hz;
705 }
706 else
707 *dresult = frac_to_double (ticks, hz);
708 return 0;
709 }
710
711
712 enum timeform
713 {
714 TIMEFORM_INVALID = 0,
715 TIMEFORM_HI_LO,
716 TIMEFORM_HI_LO_US,
717 TIMEFORM_NIL,
718 TIMEFORM_HI_LO_US_PS,
719 TIMEFORM_FLOAT,
720 TIMEFORM_TICKS_HZ
721 };
722
723
724
725
726
727
728
729
730
731
732
733
734 static int
735 decode_time_components (enum timeform form,
736 Lisp_Object high, Lisp_Object low,
737 Lisp_Object usec, Lisp_Object psec,
738 struct lisp_time *result, double *dresult)
739 {
740 switch (form)
741 {
742 case TIMEFORM_INVALID:
743 return EINVAL;
744
745 case TIMEFORM_TICKS_HZ:
746 if (INTEGERP (high)
747 && !NILP (Fnatnump (low)) && !BASE_EQ (low, make_fixnum (0)))
748 return decode_ticks_hz (high, low, result, dresult);
749 return EINVAL;
750
751 case TIMEFORM_FLOAT:
752 eassume (false);
753
754 case TIMEFORM_NIL:
755 return decode_ticks_hz (timespec_ticks (current_timespec ()),
756 timespec_hz, result, dresult);
757
758 default:
759 break;
760 }
761
762 if (! (INTEGERP (high) && INTEGERP (low)
763 && FIXNUMP (usec) && FIXNUMP (psec)))
764 return EINVAL;
765 EMACS_INT us = XFIXNUM (usec);
766 EMACS_INT ps = XFIXNUM (psec);
767
768
769
770 us += ps / 1000000 - (ps % 1000000 < 0);
771 mpz_t *s = &mpz[1];
772 mpz_set_intmax (*s, us / 1000000 - (us % 1000000 < 0));
773 mpz_add (*s, *s, *bignum_integer (&mpz[0], low));
774 mpz_addmul_ui (*s, *bignum_integer (&mpz[0], high), 1 << LO_TIME_BITS);
775 ps = ps % 1000000 + 1000000 * (ps % 1000000 < 0);
776 us = us % 1000000 + 1000000 * (us % 1000000 < 0);
777
778 Lisp_Object hz;
779 switch (form)
780 {
781 case TIMEFORM_HI_LO:
782
783 mpz_swap (mpz[0], *s);
784 hz = make_fixnum (1);
785 break;
786
787 case TIMEFORM_HI_LO_US:
788 mpz_set_ui (mpz[0], us);
789 mpz_addmul_ui (mpz[0], *s, 1000000);
790 hz = make_fixnum (1000000);
791 break;
792
793 case TIMEFORM_HI_LO_US_PS:
794 {
795 #if FASTER_TIMEFNS && TRILLION <= ULONG_MAX
796 unsigned long i = us;
797 mpz_set_ui (mpz[0], i * 1000000 + ps);
798 mpz_addmul_ui (mpz[0], *s, TRILLION);
799 #else
800 intmax_t i = us;
801 mpz_set_intmax (mpz[0], i * 1000000 + ps);
802 mpz_addmul (mpz[0], *s, ztrillion);
803 #endif
804 hz = trillion;
805 }
806 break;
807
808 default:
809 eassume (false);
810 }
811
812 return decode_ticks_hz (make_integer_mpz (), hz, result, dresult);
813 }
814
815
816
817
818
819
820
821
822
823
824
825
826 static enum timeform
827 decode_lisp_time (Lisp_Object specified_time, bool decode_secs_only,
828 struct lisp_time *result, double *dresult)
829 {
830 Lisp_Object high = make_fixnum (0);
831 Lisp_Object low = specified_time;
832 Lisp_Object usec = make_fixnum (0);
833 Lisp_Object psec = make_fixnum (0);
834 enum timeform form = TIMEFORM_HI_LO;
835
836 if (NILP (specified_time))
837 form = TIMEFORM_NIL;
838 else if (CONSP (specified_time))
839 {
840 high = XCAR (specified_time);
841 low = XCDR (specified_time);
842 if (CONSP (low))
843 {
844 Lisp_Object low_tail = XCDR (low);
845 low = XCAR (low);
846 if (! decode_secs_only)
847 {
848 if (CONSP (low_tail))
849 {
850 usec = XCAR (low_tail);
851 low_tail = XCDR (low_tail);
852 if (CONSP (low_tail))
853 {
854 psec = XCAR (low_tail);
855 form = TIMEFORM_HI_LO_US_PS;
856 }
857 else
858 form = TIMEFORM_HI_LO_US;
859 }
860 else if (!NILP (low_tail))
861 {
862 usec = low_tail;
863 form = TIMEFORM_HI_LO_US;
864 }
865 }
866 }
867 else
868 {
869 form = TIMEFORM_TICKS_HZ;
870 }
871
872
873
874 if (! INTEGERP (low))
875 form = TIMEFORM_INVALID;
876 }
877 else if (FASTER_TIMEFNS && INTEGERP (specified_time))
878 {
879 decode_ticks_hz (specified_time, make_fixnum (1), result, dresult);
880 return form;
881 }
882 else if (FLOATP (specified_time))
883 {
884 double d = XFLOAT_DATA (specified_time);
885 if (!isfinite (d))
886 time_error (isnan (d) ? EDOM : EOVERFLOW);
887 if (result)
888 decode_float_time (d, result);
889 else
890 *dresult = d;
891 return TIMEFORM_FLOAT;
892 }
893
894 int err = decode_time_components (form, high, low, usec, psec,
895 result, dresult);
896 if (err)
897 time_error (err);
898 return form;
899 }
900
901
902
903 double
904 float_time (Lisp_Object specified_time)
905 {
906 double t;
907 decode_lisp_time (specified_time, false, 0, &t);
908 return t;
909 }
910
911
912 static bool
913 mpz_time (mpz_t const z, time_t *t)
914 {
915 if (TYPE_SIGNED (time_t))
916 {
917 intmax_t i;
918 if (! (mpz_to_intmax (z, &i) && TIME_T_MIN <= i && i <= TIME_T_MAX))
919 return false;
920 *t = i;
921 }
922 else
923 {
924 uintmax_t i;
925 if (! (mpz_to_uintmax (z, &i) && i <= TIME_T_MAX))
926 return false;
927 *t = i;
928 }
929 return true;
930 }
931
932
933
934 static struct timespec
935 lisp_to_timespec (struct lisp_time t)
936 {
937 struct timespec result = invalid_timespec ();
938 int ns;
939 mpz_t *q = &mpz[0];
940 mpz_t const *qt = q;
941
942
943
944
945
946 if (FASTER_TIMEFNS && BASE_EQ (t.hz, timespec_hz))
947 {
948 if (FIXNUMP (t.ticks))
949 {
950 EMACS_INT s = XFIXNUM (t.ticks) / TIMESPEC_HZ;
951 ns = XFIXNUM (t.ticks) % TIMESPEC_HZ;
952 if (ns < 0)
953 s--, ns += TIMESPEC_HZ;
954 if ((TYPE_SIGNED (time_t) ? TIME_T_MIN <= s : 0 <= s)
955 && s <= TIME_T_MAX)
956 {
957 result.tv_sec = s;
958 result.tv_nsec = ns;
959 }
960 return result;
961 }
962 else
963 ns = mpz_fdiv_q_ui (*q, *xbignum_val (t.ticks), TIMESPEC_HZ);
964 }
965 else if (FASTER_TIMEFNS && BASE_EQ (t.hz, make_fixnum (1)))
966 {
967 ns = 0;
968 if (FIXNUMP (t.ticks))
969 {
970 EMACS_INT s = XFIXNUM (t.ticks);
971 if ((TYPE_SIGNED (time_t) ? TIME_T_MIN <= s : 0 <= s)
972 && s <= TIME_T_MAX)
973 {
974 result.tv_sec = s;
975 result.tv_nsec = ns;
976 }
977 return result;
978 }
979 else
980 qt = xbignum_val (t.ticks);
981 }
982 else
983 {
984 mpz_mul_ui (*q, *bignum_integer (q, t.ticks), TIMESPEC_HZ);
985 mpz_fdiv_q (*q, *q, *bignum_integer (&mpz[1], t.hz));
986 ns = mpz_fdiv_q_ui (*q, *q, TIMESPEC_HZ);
987 }
988
989
990
991 time_t sec;
992 if (mpz_time (*qt, &sec))
993 {
994 result.tv_sec = sec;
995 result.tv_nsec = ns;
996 }
997 return result;
998 }
999
1000
1001
1002 bool
1003 list4_to_timespec (Lisp_Object high, Lisp_Object low,
1004 Lisp_Object usec, Lisp_Object psec,
1005 struct timespec *result)
1006 {
1007 struct lisp_time t;
1008 if (decode_time_components (TIMEFORM_HI_LO_US_PS, high, low, usec, psec,
1009 &t, 0))
1010 return false;
1011 *result = lisp_to_timespec (t);
1012 return timespec_valid_p (*result);
1013 }
1014
1015
1016
1017
1018
1019 static struct lisp_time
1020 lisp_time_struct (Lisp_Object specified_time, enum timeform *pform)
1021 {
1022 struct lisp_time t;
1023 enum timeform form = decode_lisp_time (specified_time, false, &t, 0);
1024 if (pform)
1025 *pform = form;
1026 return t;
1027 }
1028
1029
1030
1031
1032
1033 struct timespec
1034 lisp_time_argument (Lisp_Object specified_time)
1035 {
1036 struct lisp_time lt = lisp_time_struct (specified_time, 0);
1037 struct timespec t = lisp_to_timespec (lt);
1038 if (! timespec_valid_p (t))
1039 time_overflow ();
1040 return t;
1041 }
1042
1043
1044
1045 static time_t
1046 lisp_seconds_argument (Lisp_Object specified_time)
1047 {
1048 struct lisp_time lt;
1049 decode_lisp_time (specified_time, true, <, 0);
1050 struct timespec t = lisp_to_timespec (lt);
1051 if (! timespec_valid_p (t))
1052 time_overflow ();
1053 return t.tv_sec;
1054 }
1055
1056
1057
1058
1059 static Lisp_Object
1060 lispint_arith (Lisp_Object a, Lisp_Object b, bool subtract)
1061 {
1062 bool mpz_done = false;
1063
1064 if (FASTER_TIMEFNS && FIXNUMP (b))
1065 {
1066 if (BASE_EQ (b, make_fixnum (0)))
1067 return a;
1068
1069
1070 if (FIXNUMP (a))
1071 return make_int (subtract
1072 ? XFIXNUM (a) - XFIXNUM (b)
1073 : XFIXNUM (a) + XFIXNUM (b));
1074
1075
1076 if (eabs (XFIXNUM (b)) <= ULONG_MAX)
1077 {
1078 ((XFIXNUM (b) < 0) == subtract ? mpz_add_ui : mpz_sub_ui)
1079 (mpz[0], *xbignum_val (a), eabs (XFIXNUM (b)));
1080 mpz_done = true;
1081 }
1082 }
1083
1084
1085 if (!mpz_done)
1086 (subtract ? mpz_sub : mpz_add) (mpz[0],
1087 *bignum_integer (&mpz[0], a),
1088 *bignum_integer (&mpz[1], b));
1089 return make_integer_mpz ();
1090 }
1091
1092
1093
1094 static Lisp_Object
1095 time_arith (Lisp_Object a, Lisp_Object b, bool subtract)
1096 {
1097 enum timeform aform, bform;
1098 struct lisp_time ta = lisp_time_struct (a, &aform);
1099 struct lisp_time tb = lisp_time_struct (b, &bform);
1100 Lisp_Object ticks, hz;
1101
1102 if (FASTER_TIMEFNS && BASE_EQ (ta.hz, tb.hz))
1103 {
1104 hz = ta.hz;
1105 ticks = lispint_arith (ta.ticks, tb.ticks, subtract);
1106 }
1107 else
1108 {
1109
1110
1111
1112
1113 mpz_t const *da = bignum_integer (&mpz[1], ta.hz);
1114 mpz_t const *db = bignum_integer (&mpz[2], tb.hz);
1115 bool da_lt_db = mpz_cmp (*da, *db) < 0;
1116 mpz_t const *hzmin = da_lt_db ? da : db;
1117 mpz_t *iticks = &mpz[da_lt_db + 1];
1118
1119
1120
1121 mpz_t *g = &mpz[3];
1122 mpz_gcd (*g, *da, *db);
1123
1124
1125 mpz_t *fa = &mpz[4], *fb = &mpz[3];
1126 mpz_divexact (*fa, *da, *g);
1127 mpz_divexact (*fb, *db, *g);
1128
1129
1130 mpz_t *ihz = &mpz[0];
1131 mpz_mul (*ihz, *fa, *db);
1132
1133
1134 mpz_t const *na = bignum_integer (iticks, ta.ticks);
1135 mpz_mul (*iticks, *fb, *na);
1136 mpz_t const *nb = bignum_integer (&mpz[3], tb.ticks);
1137 (subtract ? mpz_submul : mpz_addmul) (*iticks, *fa, *nb);
1138
1139
1140
1141
1142 mpz_t *ig = &mpz[3];
1143 mpz_gcd (*ig, *iticks, *ihz);
1144 if (!FASTER_TIMEFNS || mpz_cmp_ui (*ig, 1) > 0)
1145 {
1146 mpz_divexact (*iticks, *iticks, *ig);
1147 mpz_divexact (*ihz, *ihz, *ig);
1148
1149
1150
1151
1152
1153
1154
1155 if (!FASTER_TIMEFNS || mpz_cmp (*ihz, *hzmin) < 0)
1156 {
1157
1158
1159
1160
1161
1162 mpz_t *rescale = &mpz[3];
1163 mpz_cdiv_q (*rescale, *hzmin, *ihz);
1164 mpz_mul (*iticks, *iticks, *rescale);
1165 mpz_mul (*ihz, *ihz, *rescale);
1166 }
1167 }
1168
1169
1170 hz = make_integer_mpz ();
1171 mpz_swap (mpz[0], *iticks);
1172 ticks = make_integer_mpz ();
1173 }
1174
1175
1176
1177
1178
1179
1180 return (BASE_EQ (hz, make_fixnum (1))
1181 ? ticks
1182 : (!current_time_list
1183 || aform == TIMEFORM_TICKS_HZ
1184 || bform == TIMEFORM_TICKS_HZ
1185 || !trillion_factor (hz))
1186 ? Fcons (ticks, hz)
1187 : ticks_hz_list4 (ticks, hz));
1188 }
1189
1190 DEFUN ("time-add", Ftime_add, Stime_add, 2, 2, 0,
1191 doc:
1192
1193 )
1194 (Lisp_Object a, Lisp_Object b)
1195 {
1196 return time_arith (a, b, false);
1197 }
1198
1199 DEFUN ("time-subtract", Ftime_subtract, Stime_subtract, 2, 2, 0,
1200 doc:
1201
1202
1203 )
1204 (Lisp_Object a, Lisp_Object b)
1205 {
1206
1207
1208
1209 if (BASE_EQ (a, b))
1210 return make_lisp_time ((struct timespec) {0});
1211
1212 return time_arith (a, b, true);
1213 }
1214
1215
1216
1217 static EMACS_INT
1218 time_cmp (Lisp_Object a, Lisp_Object b)
1219 {
1220
1221
1222
1223 if (BASE_EQ (a, b))
1224 return 0;
1225
1226
1227
1228
1229 if (FASTER_TIMEFNS)
1230 {
1231 Lisp_Object x = a, y = b;
1232 if (CONSP (a) && CONSP (b) && BASE_EQ (XCDR (a), XCDR (b)))
1233 x = XCAR (a), y = XCAR (b);
1234 if (FIXNUMP (x) && FIXNUMP (y))
1235 return XFIXNUM (x) - XFIXNUM (y);
1236 }
1237
1238
1239
1240 struct lisp_time ta = lisp_time_struct (a, 0);
1241 struct lisp_time tb = lisp_time_struct (b, 0);
1242 mpz_t const *za = bignum_integer (&mpz[0], ta.ticks);
1243 mpz_t const *zb = bignum_integer (&mpz[1], tb.ticks);
1244 if (! (FASTER_TIMEFNS && BASE_EQ (ta.hz, tb.hz)))
1245 {
1246
1247
1248
1249 mpz_mul (mpz[0], *za, *bignum_integer (&mpz[2], tb.hz));
1250 mpz_mul (mpz[1], *zb, *bignum_integer (&mpz[2], ta.hz));
1251 za = &mpz[0];
1252 zb = &mpz[1];
1253 }
1254 return mpz_cmp (*za, *zb);
1255 }
1256
1257 DEFUN ("time-less-p", Ftime_less_p, Stime_less_p, 2, 2, 0,
1258 doc:
1259
1260 )
1261 (Lisp_Object a, Lisp_Object b)
1262 {
1263 return time_cmp (a, b) < 0 ? Qt : Qnil;
1264 }
1265
1266 DEFUN ("time-equal-p", Ftime_equal_p, Stime_equal_p, 2, 2, 0,
1267 doc:
1268 )
1269 (Lisp_Object a, Lisp_Object b)
1270 {
1271
1272
1273 return NILP (a) == NILP (b) && time_cmp (a, b) == 0 ? Qt : Qnil;
1274 }
1275
1276
1277 DEFUN ("float-time", Ffloat_time, Sfloat_time, 0, 1, 0,
1278 doc:
1279
1280
1281
1282
1283
1284
1285 )
1286 (Lisp_Object specified_time)
1287 {
1288 return (FLOATP (specified_time) ? specified_time
1289 : make_float (float_time (specified_time)));
1290 }
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303 static size_t
1304 emacs_nmemftime (char *s, size_t maxsize, const char *format,
1305 size_t format_len, const struct tm *tp, timezone_t tz, int ns)
1306 {
1307 int saved_errno = errno;
1308 size_t total = 0;
1309
1310
1311
1312
1313
1314
1315 for (;;)
1316 {
1317 errno = 0;
1318 size_t result = nstrftime (s, maxsize, format, tp, tz, ns);
1319 if (result == 0 && errno != 0)
1320 return result;
1321 if (s)
1322 s += result + 1;
1323
1324 maxsize -= result + 1;
1325 total += result;
1326 size_t len = strlen (format);
1327 if (len == format_len)
1328 break;
1329 total++;
1330 format += len + 1;
1331 format_len -= len + 1;
1332 }
1333
1334 errno = saved_errno;
1335 return total;
1336 }
1337
1338 static Lisp_Object
1339 format_time_string (char const *format, ptrdiff_t formatlen,
1340 struct timespec t, Lisp_Object zone, struct tm *tmp)
1341 {
1342 char buffer[4000];
1343 char *buf = buffer;
1344 ptrdiff_t size = sizeof buffer;
1345 size_t len;
1346 int ns = t.tv_nsec;
1347 USE_SAFE_ALLOCA;
1348
1349 timezone_t tz = tzlookup (zone, false);
1350
1351
1352
1353 time_t tsec = t.tv_sec;
1354 tmp = emacs_localtime_rz (tz, &tsec, tmp);
1355 if (! tmp)
1356 {
1357 int localtime_errno = errno;
1358 xtzfree (tz);
1359 time_error (localtime_errno);
1360 }
1361 synchronize_system_time_locale ();
1362
1363 while (true)
1364 {
1365 errno = 0;
1366 len = emacs_nmemftime (buf, size, format, formatlen, tmp, tz, ns);
1367 if (len != 0 || errno == 0)
1368 break;
1369 eassert (errno == ERANGE);
1370
1371
1372 len = emacs_nmemftime (NULL, SIZE_MAX, format, formatlen, tmp, tz, ns);
1373 if (STRING_BYTES_BOUND <= len)
1374 {
1375 xtzfree (tz);
1376 string_overflow ();
1377 }
1378 size = len + 1;
1379 buf = SAFE_ALLOCA (size);
1380 }
1381
1382 xtzfree (tz);
1383 AUTO_STRING_WITH_LEN (bufstring, buf, len);
1384 Lisp_Object result = code_convert_string_norecord (bufstring,
1385 Vlocale_coding_system, 0);
1386 SAFE_FREE ();
1387 return result;
1388 }
1389
1390 DEFUN ("format-time-string", Fformat_time_string, Sformat_time_string, 1, 3, 0,
1391 doc:
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465 )
1466 (Lisp_Object format_string, Lisp_Object timeval, Lisp_Object zone)
1467 {
1468 struct timespec t = lisp_time_argument (timeval);
1469 struct tm tm;
1470
1471 CHECK_STRING (format_string);
1472 format_string = code_convert_string_norecord (format_string,
1473 Vlocale_coding_system, 1);
1474 return format_time_string (SSDATA (format_string), SBYTES (format_string),
1475 t, zone, &tm);
1476 }
1477
1478 DEFUN ("decode-time", Fdecode_time, Sdecode_time, 0, 3, 0,
1479 doc:
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514 )
1515 (Lisp_Object specified_time, Lisp_Object zone, Lisp_Object form)
1516 {
1517
1518 struct lisp_time lt = lisp_time_struct (specified_time, 0);
1519 struct timespec ts = lisp_to_timespec (lt);
1520 if (! timespec_valid_p (ts))
1521 time_overflow ();
1522 time_t time_spec = ts.tv_sec;
1523 struct tm local_tm, gmt_tm;
1524 timezone_t tz = tzlookup (zone, false);
1525 struct tm *tm = emacs_localtime_rz (tz, &time_spec, &local_tm);
1526 int localtime_errno = errno;
1527 xtzfree (tz);
1528
1529 if (!tm)
1530 time_error (localtime_errno);
1531
1532
1533 Lisp_Object year;
1534 if (FASTER_TIMEFNS
1535 && MOST_NEGATIVE_FIXNUM - TM_YEAR_BASE <= local_tm.tm_year
1536 && local_tm.tm_year <= MOST_POSITIVE_FIXNUM - TM_YEAR_BASE)
1537 {
1538
1539 EMACS_INT tm_year_base = TM_YEAR_BASE;
1540 year = make_fixnum (local_tm.tm_year + tm_year_base);
1541 }
1542 else
1543 {
1544 mpz_set_si (mpz[0], local_tm.tm_year);
1545 mpz_add_ui (mpz[0], mpz[0], TM_YEAR_BASE);
1546 year = make_integer_mpz ();
1547 }
1548
1549
1550 Lisp_Object hz = lt.hz, sec;
1551 if (BASE_EQ (hz, make_fixnum (1)) || !BASE2_EQ (form, Qt))
1552 sec = make_fixnum (local_tm.tm_sec);
1553 else
1554 {
1555
1556
1557 Lisp_Object ticks;
1558 intmax_t n;
1559 if (FASTER_TIMEFNS && FIXNUMP (lt.ticks) && FIXNUMP (hz)
1560 && !INT_MULTIPLY_WRAPV (XFIXNUM (hz), local_tm.tm_sec, &n)
1561 && ! (INT_ADD_WRAPV
1562 (n, (XFIXNUM (lt.ticks) % XFIXNUM (hz)
1563 + (XFIXNUM (lt.ticks) % XFIXNUM (hz) < 0
1564 ? XFIXNUM (hz) : 0)),
1565 &n)))
1566 ticks = make_int (n);
1567 else
1568 {
1569 mpz_fdiv_r (mpz[0],
1570 *bignum_integer (&mpz[0], lt.ticks),
1571 *bignum_integer (&mpz[1], hz));
1572 mpz_addmul_ui (mpz[0], *bignum_integer (&mpz[1], hz),
1573 local_tm.tm_sec);
1574 ticks = make_integer_mpz ();
1575 }
1576 sec = Fcons (ticks, hz);
1577 }
1578
1579 return CALLN (Flist,
1580 sec,
1581 make_fixnum (local_tm.tm_min),
1582 make_fixnum (local_tm.tm_hour),
1583 make_fixnum (local_tm.tm_mday),
1584 make_fixnum (local_tm.tm_mon + 1),
1585 year,
1586 make_fixnum (local_tm.tm_wday),
1587 (local_tm.tm_isdst < 0 ? make_fixnum (-1)
1588 : local_tm.tm_isdst == 0 ? Qnil : Qt),
1589 (HAVE_TM_GMTOFF
1590 ? make_fixnum (tm_gmtoff (&local_tm))
1591 : gmtime_r (&time_spec, &gmt_tm)
1592 ? make_fixnum (tm_diff (&local_tm, &gmt_tm))
1593 : Qnil));
1594 }
1595
1596
1597
1598 static int
1599 check_tm_member (Lisp_Object obj, int offset)
1600 {
1601 if (FASTER_TIMEFNS && INT_MAX <= MOST_POSITIVE_FIXNUM - TM_YEAR_BASE)
1602 {
1603 CHECK_FIXNUM (obj);
1604 EMACS_INT n = XFIXNUM (obj);
1605 int i;
1606 if (INT_SUBTRACT_WRAPV (n, offset, &i))
1607 time_overflow ();
1608 return i;
1609 }
1610 else
1611 {
1612 CHECK_INTEGER (obj);
1613 mpz_sub_ui (mpz[0], *bignum_integer (&mpz[0], obj), offset);
1614 intmax_t i;
1615 if (! (mpz_to_intmax (mpz[0], &i) && INT_MIN <= i && i <= INT_MAX))
1616 time_overflow ();
1617 return i;
1618 }
1619 }
1620
1621 DEFUN ("encode-time", Fencode_time, Sencode_time, 1, MANY, 0,
1622 doc:
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651 )
1652 (ptrdiff_t nargs, Lisp_Object *args)
1653 {
1654 struct tm tm;
1655 Lisp_Object zone = Qnil;
1656 Lisp_Object a = args[0];
1657 Lisp_Object secarg, minarg, hourarg, mdayarg, monarg, yeararg;
1658 tm.tm_isdst = -1;
1659
1660 if (nargs == 1)
1661 {
1662 Lisp_Object tail = a;
1663 for (int i = 0; i < 6; i++, tail = XCDR (tail))
1664 CHECK_CONS (tail);
1665 secarg = XCAR (a); a = XCDR (a);
1666 minarg = XCAR (a); a = XCDR (a);
1667 hourarg = XCAR (a); a = XCDR (a);
1668 mdayarg = XCAR (a); a = XCDR (a);
1669 monarg = XCAR (a); a = XCDR (a);
1670 yeararg = XCAR (a); a = XCDR (a);
1671 if (! NILP (a))
1672 {
1673 CHECK_CONS (a);
1674 a = XCDR (a);
1675 CHECK_CONS (a);
1676 Lisp_Object dstflag = XCAR (a); a = XCDR (a);
1677 CHECK_CONS (a);
1678 zone = XCAR (a);
1679 if (SYMBOLP (dstflag) && !FIXNUMP (zone) && !CONSP (zone))
1680 tm.tm_isdst = !NILP (dstflag);
1681 }
1682 }
1683 else if (nargs < 6)
1684 xsignal2 (Qwrong_number_of_arguments, Qencode_time, make_fixnum (nargs));
1685 else
1686 {
1687 if (6 < nargs)
1688 zone = args[nargs - 1];
1689 secarg = a;
1690 minarg = args[1];
1691 hourarg = args[2];
1692 mdayarg = args[3];
1693 monarg = args[4];
1694 yeararg = args[5];
1695 }
1696
1697
1698 struct lisp_time lt;
1699 decode_lisp_time (secarg, false, <, 0);
1700 Lisp_Object hz = lt.hz, sec, subsecticks;
1701 if (FASTER_TIMEFNS && BASE_EQ (hz, make_fixnum (1)))
1702 {
1703 sec = lt.ticks;
1704 subsecticks = make_fixnum (0);
1705 }
1706 else
1707 {
1708 mpz_fdiv_qr (mpz[0], mpz[1],
1709 *bignum_integer (&mpz[0], lt.ticks),
1710 *bignum_integer (&mpz[1], hz));
1711 sec = make_integer_mpz ();
1712 mpz_swap (mpz[0], mpz[1]);
1713 subsecticks = make_integer_mpz ();
1714 }
1715 tm.tm_sec = check_tm_member (sec, 0);
1716 tm.tm_min = check_tm_member (minarg, 0);
1717 tm.tm_hour = check_tm_member (hourarg, 0);
1718 tm.tm_mday = check_tm_member (mdayarg, 0);
1719 tm.tm_mon = check_tm_member (monarg, 1);
1720 tm.tm_year = check_tm_member (yeararg, TM_YEAR_BASE);
1721
1722 timezone_t tz = tzlookup (zone, false);
1723 tm.tm_wday = -1;
1724 time_t value = mktime_z (tz, &tm);
1725 int mktime_errno = errno;
1726 xtzfree (tz);
1727
1728 if (tm.tm_wday < 0)
1729 time_error (mktime_errno);
1730
1731 if (BASE_EQ (hz, make_fixnum (1)))
1732 return (current_time_list
1733 ? list2 (hi_time (value), lo_time (value))
1734 : INT_TO_INTEGER (value));
1735 else
1736 {
1737 struct lisp_time val1 = { INT_TO_INTEGER (value), make_fixnum (1) };
1738 Lisp_Object secticks = lisp_time_hz_ticks (val1, hz);
1739 Lisp_Object ticks = lispint_arith (secticks, subsecticks, false);
1740 return Fcons (ticks, hz);
1741 }
1742 }
1743
1744 DEFUN ("time-convert", Ftime_convert, Stime_convert, 1, 2, 0,
1745 doc:
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763 )
1764 (Lisp_Object time, Lisp_Object form)
1765 {
1766
1767
1768 struct lisp_time t;
1769 enum timeform input_form = decode_lisp_time (time, false, &t, 0);
1770 if (NILP (form))
1771 form = current_time_list ? Qlist : Qt;
1772 if (symbols_with_pos_enabled && SYMBOL_WITH_POS_P (form))
1773 form = SYMBOL_WITH_POS_SYM (form);
1774 if (BASE_EQ (form, Qlist))
1775 return ticks_hz_list4 (t.ticks, t.hz);
1776 if (BASE_EQ (form, Qinteger))
1777 return FASTER_TIMEFNS && INTEGERP (time) ? time : lisp_time_seconds (t);
1778 if (BASE_EQ (form, Qt))
1779 form = t.hz;
1780 if (FASTER_TIMEFNS
1781 && input_form == TIMEFORM_TICKS_HZ && BASE_EQ (form, XCDR (time)))
1782 return time;
1783 return Fcons (lisp_time_hz_ticks (t, form), form);
1784 }
1785
1786 DEFUN ("current-time", Fcurrent_time, Scurrent_time, 0, 0, 0,
1787 doc:
1788
1789
1790
1791
1792
1793
1794
1795
1796 )
1797 (void)
1798 {
1799 return make_lisp_time (current_timespec ());
1800 }
1801
1802 #ifdef CLOCKS_PER_SEC
1803 DEFUN ("current-cpu-time", Fcurrent_cpu_time, Scurrent_cpu_time, 0, 0, 0,
1804 doc:
1805
1806
1807 )
1808 (void)
1809 {
1810 return Fcons (make_int (clock ()), make_int (CLOCKS_PER_SEC));
1811 }
1812 #endif
1813
1814 DEFUN ("current-time-string", Fcurrent_time_string, Scurrent_time_string,
1815 0, 2, 0,
1816 doc:
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832 )
1833 (Lisp_Object specified_time, Lisp_Object zone)
1834 {
1835 time_t value = lisp_seconds_argument (specified_time);
1836 timezone_t tz = tzlookup (zone, false);
1837
1838
1839
1840
1841
1842 struct tm tm;
1843 struct tm *tmp = emacs_localtime_rz (tz, &value, &tm);
1844 int localtime_errno = errno;
1845 xtzfree (tz);
1846 if (! tmp)
1847 time_error (localtime_errno);
1848
1849 static char const wday_name[][4] =
1850 { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
1851 static char const mon_name[][4] =
1852 { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
1853 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
1854 intmax_t year_base = TM_YEAR_BASE;
1855 char buf[sizeof "Mon Apr 30 12:49:17 " + INT_STRLEN_BOUND (int) + 1];
1856 int len = sprintf (buf, "%s %s%3d %02d:%02d:%02d %"PRIdMAX,
1857 wday_name[tm.tm_wday], mon_name[tm.tm_mon], tm.tm_mday,
1858 tm.tm_hour, tm.tm_min, tm.tm_sec,
1859 tm.tm_year + year_base);
1860
1861 return make_unibyte_string (buf, len);
1862 }
1863
1864 DEFUN ("current-time-zone", Fcurrent_time_zone, Scurrent_time_zone, 0, 2, 0,
1865 doc:
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883 )
1884 (Lisp_Object specified_time, Lisp_Object zone)
1885 {
1886 struct timespec value;
1887 struct tm local_tm, gmt_tm;
1888 Lisp_Object zone_offset, zone_name;
1889
1890 zone_offset = Qnil;
1891 value = make_timespec (lisp_seconds_argument (specified_time), 0);
1892 zone_name = format_time_string ("%Z", sizeof "%Z" - 1, value,
1893 zone, &local_tm);
1894
1895
1896
1897 time_t tsec = value.tv_sec;
1898 if (HAVE_TM_GMTOFF || gmtime_r (&tsec, &gmt_tm))
1899 {
1900 long int offset = (HAVE_TM_GMTOFF
1901 ? tm_gmtoff (&local_tm)
1902 : tm_diff (&local_tm, &gmt_tm));
1903 zone_offset = make_fixnum (offset);
1904 if (SCHARS (zone_name) == 0)
1905 {
1906
1907 long int hour = offset / 3600;
1908 int min_sec = offset % 3600;
1909 int amin_sec = min_sec < 0 ? - min_sec : min_sec;
1910 int min = amin_sec / 60;
1911 int sec = amin_sec % 60;
1912 int min_prec = min_sec ? 2 : 0;
1913 int sec_prec = sec ? 2 : 0;
1914 char buf[sizeof "+0000" + INT_STRLEN_BOUND (long int)];
1915 zone_name = make_formatted_string (buf, "%c%.2ld%.*d%.*d",
1916 (offset < 0 ? '-' : '+'),
1917 hour, min_prec, min, sec_prec, sec);
1918 }
1919 }
1920
1921 return list2 (zone_offset, zone_name);
1922 }
1923
1924 DEFUN ("set-time-zone-rule", Fset_time_zone_rule, Sset_time_zone_rule, 1, 1, 0,
1925 doc:
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939 )
1940 (Lisp_Object tz)
1941 {
1942 tzlookup (NILP (tz) ? Qwall : tz, true);
1943 return Qnil;
1944 }
1945
1946
1947
1948
1949 static char *tzvalbuf;
1950
1951
1952 char *
1953 emacs_getenv_TZ (void)
1954 {
1955 return tzvalbuf[0] == 'T' ? tzvalbuf + tzeqlen : 0;
1956 }
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966 int
1967 emacs_setenv_TZ (const char *tzstring)
1968 {
1969 static ptrdiff_t tzvalbufsize;
1970 ptrdiff_t tzstringlen = tzstring ? strlen (tzstring) : 0;
1971 char *tzval = tzvalbuf;
1972 bool new_tzvalbuf = tzvalbufsize <= tzeqlen + tzstringlen;
1973
1974 if (new_tzvalbuf)
1975 {
1976
1977
1978
1979 tzval = xpalloc (NULL, &tzvalbufsize,
1980 tzeqlen + tzstringlen - tzvalbufsize + 1, -1, 1);
1981 tzvalbuf = tzval;
1982 tzval[1] = 'Z';
1983 tzval[2] = '=';
1984 }
1985
1986 if (tzstring)
1987 {
1988
1989
1990
1991 tzval[0] = 'T';
1992 strcpy (tzval + tzeqlen, tzstring);
1993 }
1994 else
1995 {
1996
1997
1998
1999 tzval[0] = 't';
2000 tzval[tzeqlen] = 0;
2001 }
2002
2003
2004 #ifndef WINDOWSNT
2005
2006
2007
2008
2009 bool need_putenv = new_tzvalbuf;
2010 #else
2011
2012
2013
2014
2015
2016
2017 bool need_putenv = true;
2018 #endif
2019 if (need_putenv)
2020 xputenv (tzval);
2021
2022 return 0;
2023 }
2024
2025 #if (ULONG_MAX < TRILLION || !FASTER_TIMEFNS) && !defined ztrillion
2026 # define NEED_ZTRILLION_INIT 1
2027 #endif
2028
2029 #ifdef NEED_ZTRILLION_INIT
2030 static void
2031 syms_of_timefns_for_pdumper (void)
2032 {
2033 mpz_init_set_ui (ztrillion, 1000000);
2034 mpz_mul_ui (ztrillion, ztrillion, 1000000);
2035 }
2036 #endif
2037
2038 void
2039 syms_of_timefns (void)
2040 {
2041 #ifndef timespec_hz
2042 timespec_hz = make_int (TIMESPEC_HZ);
2043 staticpro (×pec_hz);
2044 #endif
2045 #ifndef trillion
2046 trillion = make_int (1000000000000);
2047 staticpro (&trillion);
2048 #endif
2049
2050 DEFSYM (Qencode_time, "encode-time");
2051
2052 DEFVAR_BOOL ("current-time-list", current_time_list,
2053 doc:
2054
2055
2056
2057
2058
2059
2060
2061
2062 );
2063 current_time_list = CURRENT_TIME_LIST;
2064
2065 defsubr (&Scurrent_time);
2066 #ifdef CLOCKS_PER_SEC
2067 defsubr (&Scurrent_cpu_time);
2068 #endif
2069 defsubr (&Stime_convert);
2070 defsubr (&Stime_add);
2071 defsubr (&Stime_subtract);
2072 defsubr (&Stime_less_p);
2073 defsubr (&Stime_equal_p);
2074 defsubr (&Sformat_time_string);
2075 defsubr (&Sfloat_time);
2076 defsubr (&Sdecode_time);
2077 defsubr (&Sencode_time);
2078 defsubr (&Scurrent_time_string);
2079 defsubr (&Scurrent_time_zone);
2080 defsubr (&Sset_time_zone_rule);
2081
2082 flt_radix_power = make_nil_vector (flt_radix_power_size);
2083 staticpro (&flt_radix_power);
2084
2085 #ifdef NEED_ZTRILLION_INIT
2086 pdumper_do_now_and_after_load (syms_of_timefns_for_pdumper);
2087 #endif
2088 }