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 && !ckd_mul (&accum, t.tv_sec, TIMESPEC_HZ)
518 && !ckd_add (&accum, accum, t.tv_nsec))
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 && !ckd_mul (&ticks, XFIXNUM (t.ticks), XFIXNUM (hz)))
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 && !ckd_mul (&n, XFIXNUM (hz), local_tm.tm_sec)
1561 && !ckd_add (&n, n, (XFIXNUM (lt.ticks) % XFIXNUM (hz)
1562 + (XFIXNUM (lt.ticks) % XFIXNUM (hz) < 0
1563 ? XFIXNUM (hz) : 0))))
1564 ticks = make_int (n);
1565 else
1566 {
1567 mpz_fdiv_r (mpz[0],
1568 *bignum_integer (&mpz[0], lt.ticks),
1569 *bignum_integer (&mpz[1], hz));
1570 mpz_addmul_ui (mpz[0], *bignum_integer (&mpz[1], hz),
1571 local_tm.tm_sec);
1572 ticks = make_integer_mpz ();
1573 }
1574 sec = Fcons (ticks, hz);
1575 }
1576
1577 return CALLN (Flist,
1578 sec,
1579 make_fixnum (local_tm.tm_min),
1580 make_fixnum (local_tm.tm_hour),
1581 make_fixnum (local_tm.tm_mday),
1582 make_fixnum (local_tm.tm_mon + 1),
1583 year,
1584 make_fixnum (local_tm.tm_wday),
1585 (local_tm.tm_isdst < 0 ? make_fixnum (-1)
1586 : local_tm.tm_isdst == 0 ? Qnil : Qt),
1587 (HAVE_TM_GMTOFF
1588 ? make_fixnum (tm_gmtoff (&local_tm))
1589 : gmtime_r (&time_spec, &gmt_tm)
1590 ? make_fixnum (tm_diff (&local_tm, &gmt_tm))
1591 : Qnil));
1592 }
1593
1594
1595
1596 static int
1597 check_tm_member (Lisp_Object obj, int offset)
1598 {
1599 if (FASTER_TIMEFNS && INT_MAX <= MOST_POSITIVE_FIXNUM - TM_YEAR_BASE)
1600 {
1601 CHECK_FIXNUM (obj);
1602 EMACS_INT n = XFIXNUM (obj);
1603 int i;
1604 if (ckd_sub (&i, n, offset))
1605 time_overflow ();
1606 return i;
1607 }
1608 else
1609 {
1610 CHECK_INTEGER (obj);
1611 mpz_sub_ui (mpz[0], *bignum_integer (&mpz[0], obj), offset);
1612 intmax_t i;
1613 if (! (mpz_to_intmax (mpz[0], &i) && INT_MIN <= i && i <= INT_MAX))
1614 time_overflow ();
1615 return i;
1616 }
1617 }
1618
1619 DEFUN ("encode-time", Fencode_time, Sencode_time, 1, MANY, 0,
1620 doc:
1621
1622
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 (ptrdiff_t nargs, Lisp_Object *args)
1651 {
1652 struct tm tm;
1653 Lisp_Object zone = Qnil;
1654 Lisp_Object a = args[0];
1655 Lisp_Object secarg, minarg, hourarg, mdayarg, monarg, yeararg;
1656 tm.tm_isdst = -1;
1657
1658 if (nargs == 1)
1659 {
1660 Lisp_Object tail = a;
1661 for (int i = 0; i < 6; i++, tail = XCDR (tail))
1662 CHECK_CONS (tail);
1663 secarg = XCAR (a); a = XCDR (a);
1664 minarg = XCAR (a); a = XCDR (a);
1665 hourarg = XCAR (a); a = XCDR (a);
1666 mdayarg = XCAR (a); a = XCDR (a);
1667 monarg = XCAR (a); a = XCDR (a);
1668 yeararg = XCAR (a); a = XCDR (a);
1669 if (! NILP (a))
1670 {
1671 CHECK_CONS (a);
1672 a = XCDR (a);
1673 CHECK_CONS (a);
1674 Lisp_Object dstflag = XCAR (a); a = XCDR (a);
1675 CHECK_CONS (a);
1676 zone = XCAR (a);
1677 if (SYMBOLP (dstflag) && !FIXNUMP (zone) && !CONSP (zone))
1678 tm.tm_isdst = !NILP (dstflag);
1679 }
1680 }
1681 else if (nargs < 6)
1682 xsignal2 (Qwrong_number_of_arguments, Qencode_time, make_fixnum (nargs));
1683 else
1684 {
1685 if (6 < nargs)
1686 zone = args[nargs - 1];
1687 secarg = a;
1688 minarg = args[1];
1689 hourarg = args[2];
1690 mdayarg = args[3];
1691 monarg = args[4];
1692 yeararg = args[5];
1693 }
1694
1695
1696 struct lisp_time lt;
1697 decode_lisp_time (secarg, false, <, 0);
1698 Lisp_Object hz = lt.hz, sec, subsecticks;
1699 if (FASTER_TIMEFNS && BASE_EQ (hz, make_fixnum (1)))
1700 {
1701 sec = lt.ticks;
1702 subsecticks = make_fixnum (0);
1703 }
1704 else
1705 {
1706 mpz_fdiv_qr (mpz[0], mpz[1],
1707 *bignum_integer (&mpz[0], lt.ticks),
1708 *bignum_integer (&mpz[1], hz));
1709 sec = make_integer_mpz ();
1710 mpz_swap (mpz[0], mpz[1]);
1711 subsecticks = make_integer_mpz ();
1712 }
1713 tm.tm_sec = check_tm_member (sec, 0);
1714 tm.tm_min = check_tm_member (minarg, 0);
1715 tm.tm_hour = check_tm_member (hourarg, 0);
1716 tm.tm_mday = check_tm_member (mdayarg, 0);
1717 tm.tm_mon = check_tm_member (monarg, 1);
1718 tm.tm_year = check_tm_member (yeararg, TM_YEAR_BASE);
1719
1720 timezone_t tz = tzlookup (zone, false);
1721 tm.tm_wday = -1;
1722 time_t value = mktime_z (tz, &tm);
1723 int mktime_errno = errno;
1724 xtzfree (tz);
1725
1726 if (tm.tm_wday < 0)
1727 time_error (mktime_errno);
1728
1729 if (BASE_EQ (hz, make_fixnum (1)))
1730 return (current_time_list
1731 ? list2 (hi_time (value), lo_time (value))
1732 : INT_TO_INTEGER (value));
1733 else
1734 {
1735 struct lisp_time val1 = { INT_TO_INTEGER (value), make_fixnum (1) };
1736 Lisp_Object secticks = lisp_time_hz_ticks (val1, hz);
1737 Lisp_Object ticks = lispint_arith (secticks, subsecticks, false);
1738 return Fcons (ticks, hz);
1739 }
1740 }
1741
1742 DEFUN ("time-convert", Ftime_convert, Stime_convert, 1, 2, 0,
1743 doc:
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761 )
1762 (Lisp_Object time, Lisp_Object form)
1763 {
1764
1765
1766 struct lisp_time t;
1767 enum timeform input_form = decode_lisp_time (time, false, &t, 0);
1768 if (NILP (form))
1769 form = current_time_list ? Qlist : Qt;
1770 if (symbols_with_pos_enabled && SYMBOL_WITH_POS_P (form))
1771 form = SYMBOL_WITH_POS_SYM (form);
1772 if (BASE_EQ (form, Qlist))
1773 return ticks_hz_list4 (t.ticks, t.hz);
1774 if (BASE_EQ (form, Qinteger))
1775 return FASTER_TIMEFNS && INTEGERP (time) ? time : lisp_time_seconds (t);
1776 if (BASE_EQ (form, Qt))
1777 form = t.hz;
1778 if (FASTER_TIMEFNS
1779 && input_form == TIMEFORM_TICKS_HZ && BASE_EQ (form, XCDR (time)))
1780 return time;
1781 return Fcons (lisp_time_hz_ticks (t, form), form);
1782 }
1783
1784 DEFUN ("current-time", Fcurrent_time, Scurrent_time, 0, 0, 0,
1785 doc:
1786
1787
1788
1789
1790
1791
1792
1793
1794 )
1795 (void)
1796 {
1797 return make_lisp_time (current_timespec ());
1798 }
1799
1800 #ifdef CLOCKS_PER_SEC
1801 DEFUN ("current-cpu-time", Fcurrent_cpu_time, Scurrent_cpu_time, 0, 0, 0,
1802 doc:
1803
1804
1805 )
1806 (void)
1807 {
1808 return Fcons (make_int (clock ()), make_int (CLOCKS_PER_SEC));
1809 }
1810 #endif
1811
1812 DEFUN ("current-time-string", Fcurrent_time_string, Scurrent_time_string,
1813 0, 2, 0,
1814 doc:
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830 )
1831 (Lisp_Object specified_time, Lisp_Object zone)
1832 {
1833 time_t value = lisp_seconds_argument (specified_time);
1834 timezone_t tz = tzlookup (zone, false);
1835
1836
1837
1838
1839
1840 struct tm tm;
1841 struct tm *tmp = emacs_localtime_rz (tz, &value, &tm);
1842 int localtime_errno = errno;
1843 xtzfree (tz);
1844 if (! tmp)
1845 time_error (localtime_errno);
1846
1847 static char const wday_name[][4] =
1848 { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
1849 static char const mon_name[][4] =
1850 { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
1851 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
1852 intmax_t year_base = TM_YEAR_BASE;
1853 char buf[sizeof "Mon Apr 30 12:49:17 " + INT_STRLEN_BOUND (int) + 1];
1854 int len = sprintf (buf, "%s %s%3d %02d:%02d:%02d %"PRIdMAX,
1855 wday_name[tm.tm_wday], mon_name[tm.tm_mon], tm.tm_mday,
1856 tm.tm_hour, tm.tm_min, tm.tm_sec,
1857 tm.tm_year + year_base);
1858
1859 return make_unibyte_string (buf, len);
1860 }
1861
1862 DEFUN ("current-time-zone", Fcurrent_time_zone, Scurrent_time_zone, 0, 2, 0,
1863 doc:
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881 )
1882 (Lisp_Object specified_time, Lisp_Object zone)
1883 {
1884 struct timespec value;
1885 struct tm local_tm, gmt_tm;
1886 Lisp_Object zone_offset, zone_name;
1887
1888 zone_offset = Qnil;
1889 value = make_timespec (lisp_seconds_argument (specified_time), 0);
1890 zone_name = format_time_string ("%Z", sizeof "%Z" - 1, value,
1891 zone, &local_tm);
1892
1893
1894
1895 time_t tsec = value.tv_sec;
1896 if (HAVE_TM_GMTOFF || gmtime_r (&tsec, &gmt_tm))
1897 {
1898 long int offset = (HAVE_TM_GMTOFF
1899 ? tm_gmtoff (&local_tm)
1900 : tm_diff (&local_tm, &gmt_tm));
1901 zone_offset = make_fixnum (offset);
1902 if (SCHARS (zone_name) == 0)
1903 {
1904
1905 long int hour = offset / 3600;
1906 int min_sec = offset % 3600;
1907 int amin_sec = min_sec < 0 ? - min_sec : min_sec;
1908 int min = amin_sec / 60;
1909 int sec = amin_sec % 60;
1910 int min_prec = min_sec ? 2 : 0;
1911 int sec_prec = sec ? 2 : 0;
1912 char buf[sizeof "+0000" + INT_STRLEN_BOUND (long int)];
1913 zone_name = make_formatted_string (buf, "%c%.2ld%.*d%.*d",
1914 (offset < 0 ? '-' : '+'),
1915 hour, min_prec, min, sec_prec, sec);
1916 }
1917 }
1918
1919 return list2 (zone_offset, zone_name);
1920 }
1921
1922 DEFUN ("set-time-zone-rule", Fset_time_zone_rule, Sset_time_zone_rule, 1, 1, 0,
1923 doc:
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937 )
1938 (Lisp_Object tz)
1939 {
1940 tzlookup (NILP (tz) ? Qwall : tz, true);
1941 return Qnil;
1942 }
1943
1944
1945
1946
1947 static char *tzvalbuf;
1948
1949
1950 char *
1951 emacs_getenv_TZ (void)
1952 {
1953 return tzvalbuf[0] == 'T' ? tzvalbuf + tzeqlen : 0;
1954 }
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964 int
1965 emacs_setenv_TZ (const char *tzstring)
1966 {
1967 static ptrdiff_t tzvalbufsize;
1968 ptrdiff_t tzstringlen = tzstring ? strlen (tzstring) : 0;
1969 char *tzval = tzvalbuf;
1970 bool new_tzvalbuf = tzvalbufsize <= tzeqlen + tzstringlen;
1971
1972 if (new_tzvalbuf)
1973 {
1974
1975
1976
1977 tzval = xpalloc (NULL, &tzvalbufsize,
1978 tzeqlen + tzstringlen - tzvalbufsize + 1, -1, 1);
1979 tzvalbuf = tzval;
1980 tzval[1] = 'Z';
1981 tzval[2] = '=';
1982 }
1983
1984 if (tzstring)
1985 {
1986
1987
1988
1989 tzval[0] = 'T';
1990 strcpy (tzval + tzeqlen, tzstring);
1991 }
1992 else
1993 {
1994
1995
1996
1997 tzval[0] = 't';
1998 tzval[tzeqlen] = 0;
1999 }
2000
2001
2002 #ifndef WINDOWSNT
2003
2004
2005
2006
2007 bool need_putenv = new_tzvalbuf;
2008 #else
2009
2010
2011
2012
2013
2014
2015 bool need_putenv = true;
2016 #endif
2017 if (need_putenv)
2018 xputenv (tzval);
2019
2020 return 0;
2021 }
2022
2023 #if (ULONG_MAX < TRILLION || !FASTER_TIMEFNS) && !defined ztrillion
2024 # define NEED_ZTRILLION_INIT 1
2025 #endif
2026
2027 #ifdef NEED_ZTRILLION_INIT
2028 static void
2029 syms_of_timefns_for_pdumper (void)
2030 {
2031 mpz_init_set_ui (ztrillion, 1000000);
2032 mpz_mul_ui (ztrillion, ztrillion, 1000000);
2033 }
2034 #endif
2035
2036 void
2037 syms_of_timefns (void)
2038 {
2039 #ifndef timespec_hz
2040 timespec_hz = make_int (TIMESPEC_HZ);
2041 staticpro (×pec_hz);
2042 #endif
2043 #ifndef trillion
2044 trillion = make_int (1000000000000);
2045 staticpro (&trillion);
2046 #endif
2047
2048 DEFSYM (Qencode_time, "encode-time");
2049
2050 DEFVAR_BOOL ("current-time-list", current_time_list,
2051 doc:
2052
2053
2054
2055
2056
2057
2058
2059
2060 );
2061 current_time_list = CURRENT_TIME_LIST;
2062
2063 defsubr (&Scurrent_time);
2064 #ifdef CLOCKS_PER_SEC
2065 defsubr (&Scurrent_cpu_time);
2066 #endif
2067 defsubr (&Stime_convert);
2068 defsubr (&Stime_add);
2069 defsubr (&Stime_subtract);
2070 defsubr (&Stime_less_p);
2071 defsubr (&Stime_equal_p);
2072 defsubr (&Sformat_time_string);
2073 defsubr (&Sfloat_time);
2074 defsubr (&Sdecode_time);
2075 defsubr (&Sencode_time);
2076 defsubr (&Scurrent_time_string);
2077 defsubr (&Scurrent_time_zone);
2078 defsubr (&Sset_time_zone_rule);
2079
2080 flt_radix_power = make_nil_vector (flt_radix_power_size);
2081 staticpro (&flt_radix_power);
2082
2083 #ifdef NEED_ZTRILLION_INIT
2084 pdumper_do_now_and_after_load (syms_of_timefns_for_pdumper);
2085 #endif
2086 }