xref: /netbsd-src/lib/libc/time/private.h (revision aef5eb5f59cdfe8314f1b5f78ac04eb144e44010)
1 /* Private header for tzdb code.  */
2 
3 /*	$NetBSD: private.h,v 1.60 2022/08/16 11:07:40 christos Exp $	*/
4 
5 #ifndef PRIVATE_H
6 #define PRIVATE_H
7 
8 /* NetBSD defaults */
9 #define TM_GMTOFF	tm_gmtoff
10 #define TM_ZONE		tm_zone
11 #define STD_INSPIRED	1
12 #define HAVE_LONG_DOUBLE 1
13 
14 /* For when we build zic as a host tool. */
15 #if HAVE_NBTOOL_CONFIG_H
16 #include "nbtool_config.h"
17 #endif
18 
19 /*
20 ** This file is in the public domain, so clarified as of
21 ** 1996-06-05 by Arthur David Olson.
22 */
23 
24 /*
25 ** This header is for use ONLY with the time conversion code.
26 ** There is no guarantee that it will remain unchanged,
27 ** or that it will remain at all.
28 ** Do NOT copy it to any system include directory.
29 ** Thank you!
30 */
31 
32 /*
33 ** zdump has been made independent of the rest of the time
34 ** conversion package to increase confidence in the verification it provides.
35 ** You can use zdump to help in verifying other implementations.
36 ** To do this, compile with -DUSE_LTZ=0 and link without the tz library.
37 */
38 #ifndef USE_LTZ
39 # define USE_LTZ 1
40 #endif
41 
42 /* This string was in the Factory zone through version 2016f.  */
43 #define GRANDPARENTED	"Local time zone must be set--see zic manual page"
44 
45 /*
46 ** Defaults for preprocessor symbols.
47 ** You can override these in your C compiler options, e.g. '-DHAVE_GETTEXT=1'.
48 */
49 
50 #ifndef HAVE_DECL_ASCTIME_R
51 # define HAVE_DECL_ASCTIME_R 1
52 #endif
53 
54 #if !defined HAVE_GENERIC && defined __has_extension
55 # if __has_extension(c_generic_selections)
56 #  define HAVE_GENERIC 1
57 # else
58 #  define HAVE_GENERIC 0
59 # endif
60 #endif
61 /* _Generic is buggy in pre-4.9 GCC.  */
62 #if !defined HAVE_GENERIC && defined __GNUC__
63 # define HAVE_GENERIC (4 < __GNUC__ + (9 <= __GNUC_MINOR__))
64 #endif
65 #ifndef HAVE_GENERIC
66 # define HAVE_GENERIC (201112 <= __STDC_VERSION__)
67 #endif
68 
69 #ifndef HAVE_GETTEXT
70 # define HAVE_GETTEXT 0
71 #endif /* !defined HAVE_GETTEXT */
72 
73 #ifndef HAVE_INCOMPATIBLE_CTIME_R
74 # define HAVE_INCOMPATIBLE_CTIME_R 0
75 #endif
76 
77 #ifndef HAVE_LINK
78 # define HAVE_LINK 1
79 #endif /* !defined HAVE_LINK */
80 
81 #ifndef HAVE_MALLOC_ERRNO
82 # define HAVE_MALLOC_ERRNO 1
83 #endif
84 
85 #ifndef HAVE_POSIX_DECLS
86 # define HAVE_POSIX_DECLS 1
87 #endif
88 
89 #ifndef HAVE_STDBOOL_H
90 # define HAVE_STDBOOL_H (199901 <= __STDC_VERSION__)
91 #endif
92 
93 #ifndef HAVE_STRDUP
94 # define HAVE_STRDUP 1
95 #endif
96 
97 #ifndef HAVE_STRTOLL
98 # define HAVE_STRTOLL 1
99 #endif
100 
101 #ifndef HAVE_SYMLINK
102 # define HAVE_SYMLINK 1
103 #endif /* !defined HAVE_SYMLINK */
104 
105 #ifndef HAVE_SYS_STAT_H
106 # define HAVE_SYS_STAT_H 1
107 #endif /* !defined HAVE_SYS_STAT_H */
108 
109 #ifndef HAVE_UNISTD_H
110 # define HAVE_UNISTD_H 1
111 #endif /* !defined HAVE_UNISTD_H */
112 
113 #ifndef HAVE_UTMPX_H
114 # define HAVE_UTMPX_H 1
115 #endif /* !defined HAVE_UTMPX_H */
116 
117 #ifndef NETBSD_INSPIRED
118 # define NETBSD_INSPIRED 1
119 #endif
120 
121 #if HAVE_INCOMPATIBLE_CTIME_R
122 # define asctime_r _incompatible_asctime_r
123 # define ctime_r _incompatible_ctime_r
124 #endif /* HAVE_INCOMPATIBLE_CTIME_R */
125 
126 /* Enable tm_gmtoff, tm_zone, and environ on GNUish systems.  */
127 #define _GNU_SOURCE 1
128 /* Fix asctime_r on Solaris 11.  */
129 #define _POSIX_PTHREAD_SEMANTICS 1
130 /* Enable strtoimax on pre-C99 Solaris 11.  */
131 #define __EXTENSIONS__ 1
132 
133 /* To avoid having 'stat' fail unnecessarily with errno == EOVERFLOW,
134    enable large files on GNUish systems ...  */
135 #ifndef _FILE_OFFSET_BITS
136 # define _FILE_OFFSET_BITS 64
137 #endif
138 /* ... and on AIX ...  */
139 #define _LARGE_FILES 1
140 /* ... and enable large inode numbers on Mac OS X 10.5 and later.  */
141 #define _DARWIN_USE_64_BIT_INODE 1
142 
143 /*
144 ** Nested includes
145 */
146 
147 #ifndef __NetBSD__
148 /* Avoid clashes with NetBSD by renaming NetBSD's declarations.
149    If defining the 'timezone' variable, avoid a clash with FreeBSD's
150    'timezone' function by renaming its declaration.  */
151 #define localtime_rz sys_localtime_rz
152 #define mktime_z sys_mktime_z
153 #define posix2time_z sys_posix2time_z
154 #define time2posix_z sys_time2posix_z
155 #if defined USG_COMPAT && USG_COMPAT == 2
156 # define timezone sys_timezone
157 #endif
158 #define timezone_t sys_timezone_t
159 #define tzalloc sys_tzalloc
160 #define tzfree sys_tzfree
161 #include <time.h>
162 #undef localtime_rz
163 #undef mktime_z
164 #undef posix2time_z
165 #undef time2posix_z
166 #if defined USG_COMPAT && USG_COMPAT == 2
167 # undef timezone
168 #endif
169 #undef timezone_t
170 #undef tzalloc
171 #undef tzfree
172 #else
173 #include "time.h"
174 #endif
175 
176 #include <sys/types.h>	/* for time_t */
177 #include <string.h>
178 #include <limits.h>	/* for CHAR_BIT et al. */
179 #include <stdlib.h>
180 
181 #include <errno.h>
182 
183 #ifndef EINVAL
184 # define EINVAL ERANGE
185 #endif
186 
187 #ifndef ELOOP
188 # define ELOOP EINVAL
189 #endif
190 #ifndef ENAMETOOLONG
191 # define ENAMETOOLONG EINVAL
192 #endif
193 #ifndef ENOMEM
194 # define ENOMEM EINVAL
195 #endif
196 #ifndef ENOTSUP
197 # define ENOTSUP EINVAL
198 #endif
199 #ifndef EOVERFLOW
200 # define EOVERFLOW EINVAL
201 #endif
202 
203 #if HAVE_GETTEXT
204 # include <libintl.h>
205 #endif /* HAVE_GETTEXT */
206 
207 #if HAVE_UNISTD_H
208 # include <unistd.h> /* for R_OK, and other POSIX goodness */
209 #endif /* HAVE_UNISTD_H */
210 
211 #ifndef HAVE_STRFTIME_L
212 # if _POSIX_VERSION < 200809
213 #  define HAVE_STRFTIME_L 0
214 # else
215 #  define HAVE_STRFTIME_L 1
216 # endif
217 #endif
218 
219 #ifndef USG_COMPAT
220 # ifndef _XOPEN_VERSION
221 #  define USG_COMPAT 0
222 # else
223 #  define USG_COMPAT 1
224 # endif
225 #endif
226 
227 #ifndef HAVE_TZNAME
228 # if _POSIX_VERSION < 198808 && !USG_COMPAT
229 #  define HAVE_TZNAME 0
230 # else
231 #  define HAVE_TZNAME 1
232 # endif
233 #endif
234 
235 #ifndef ALTZONE
236 # if defined __sun || defined _M_XENIX
237 #  define ALTZONE 1
238 # else
239 #  define ALTZONE 0
240 # endif
241 #endif
242 
243 #ifndef R_OK
244 # define R_OK 4
245 #endif /* !defined R_OK */
246 
247 /*
248 ** Define HAVE_STDINT_H's default value here, rather than at the
249 ** start, since __GLIBC__ and INTMAX_MAX's values depend on
250 ** previously-included files.  glibc 2.1 and Solaris 10 and later have
251 ** stdint.h, even with pre-C99 compilers.
252 */
253 #ifndef HAVE_STDINT_H
254 # define HAVE_STDINT_H \
255    (199901 <= __STDC_VERSION__ \
256     || 2 < __GLIBC__ + (1 <= __GLIBC_MINOR__) \
257     || __CYGWIN__ || INTMAX_MAX)
258 #endif /* !defined HAVE_STDINT_H */
259 
260 #if HAVE_STDINT_H
261 # include <stdint.h>
262 #endif /* !HAVE_STDINT_H */
263 
264 #ifndef HAVE_INTTYPES_H
265 # define HAVE_INTTYPES_H HAVE_STDINT_H
266 #endif
267 #if HAVE_INTTYPES_H
268 # include <inttypes.h>
269 #endif
270 
271 /* Pre-C99 GCC compilers define __LONG_LONG_MAX__ instead of LLONG_MAX.  */
272 #ifdef __LONG_LONG_MAX__
273 # ifndef LLONG_MAX
274 #  define LLONG_MAX __LONG_LONG_MAX__
275 # endif
276 # ifndef LLONG_MIN
277 #  define LLONG_MIN (-1 - LLONG_MAX)
278 # endif
279 #endif
280 
281 #ifndef INT_FAST64_MAX
282 # ifdef LLONG_MAX
283 typedef long long	int_fast64_t;
284 #  define INT_FAST64_MIN LLONG_MIN
285 #  define INT_FAST64_MAX LLONG_MAX
286 # else
287 #  if LONG_MAX >> 31 < 0xffffffff
288 Please use a compiler that supports a 64-bit integer type (or wider);
289 you may need to compile with "-DHAVE_STDINT_H".
290 #  endif
291 typedef long		int_fast64_t;
292 #  define INT_FAST64_MIN LONG_MIN
293 #  define INT_FAST64_MAX LONG_MAX
294 # endif
295 #endif
296 
297 #ifndef PRIdFAST64
298 # if INT_FAST64_MAX == LLONG_MAX
299 #  define PRIdFAST64 "lld"
300 # else
301 #  define PRIdFAST64 "ld"
302 # endif
303 #endif
304 
305 #ifndef SCNdFAST64
306 # define SCNdFAST64 PRIdFAST64
307 #endif
308 
309 #ifndef INT_FAST32_MAX
310 # if INT_MAX >> 31 == 0
311 typedef long int_fast32_t;
312 #  define INT_FAST32_MAX LONG_MAX
313 #  define INT_FAST32_MIN LONG_MIN
314 # else
315 typedef int int_fast32_t;
316 #  define INT_FAST32_MAX INT_MAX
317 #  define INT_FAST32_MIN INT_MIN
318 # endif
319 #endif
320 
321 #ifndef INTMAX_MAX
322 # ifdef LLONG_MAX
323 typedef long long intmax_t;
324 #  if HAVE_STRTOLL
325 #   define strtoimax strtoll
326 #  endif
327 #  define INTMAX_MAX LLONG_MAX
328 #  define INTMAX_MIN LLONG_MIN
329 # else
330 typedef long intmax_t;
331 #  define INTMAX_MAX LONG_MAX
332 #  define INTMAX_MIN LONG_MIN
333 # endif
334 # ifndef strtoimax
335 #  define strtoimax strtol
336 # endif
337 #endif
338 
339 #ifndef PRIdMAX
340 # if INTMAX_MAX == LLONG_MAX
341 #  define PRIdMAX "lld"
342 # else
343 #  define PRIdMAX "ld"
344 # endif
345 #endif
346 
347 #ifndef UINT_FAST32_MAX
348 typedef unsigned long uint_fast32_t;
349 #endif
350 
351 #ifndef UINT_FAST64_MAX
352 # if defined ULLONG_MAX || defined __LONG_LONG_MAX__
353 typedef unsigned long long uint_fast64_t;
354 # else
355 #  if ULONG_MAX >> 31 >> 1 < 0xffffffff
356 Please use a compiler that supports a 64-bit integer type (or wider);
357 you may need to compile with "-DHAVE_STDINT_H".
358 #  endif
359 typedef unsigned long	uint_fast64_t;
360 # endif
361 #endif
362 
363 #ifndef UINTMAX_MAX
364 # if defined ULLONG_MAX || defined __LONG_LONG_MAX__
365 typedef unsigned long long uintmax_t;
366 # else
367 typedef unsigned long uintmax_t;
368 # endif
369 #endif
370 
371 #ifndef PRIuMAX
372 # if defined ULLONG_MAX || defined __LONG_LONG_MAX__
373 #  define PRIuMAX "llu"
374 # else
375 #  define PRIuMAX "lu"
376 # endif
377 #endif
378 
379 #ifndef INT32_MAX
380 # define INT32_MAX 0x7fffffff
381 #endif /* !defined INT32_MAX */
382 #ifndef INT32_MIN
383 # define INT32_MIN (-1 - INT32_MAX)
384 #endif /* !defined INT32_MIN */
385 
386 #ifndef SIZE_MAX
387 # define SIZE_MAX ((size_t) -1)
388 #endif
389 
390 #if 3 <= __GNUC__
391 # define ATTRIBUTE_CONST __attribute__((__const__))
392 # define ATTRIBUTE_MALLOC __attribute__((__malloc__))
393 # define ATTRIBUTE_PURE __attribute__((__pure__))
394 # define ATTRIBUTE_FORMAT(spec) __attribute__((__format__ spec))
395 #else
396 # define ATTRIBUTE_CONST /* empty */
397 # define ATTRIBUTE_MALLOC /* empty */
398 # define ATTRIBUTE_PURE /* empty */
399 # define ATTRIBUTE_FORMAT(spec) /* empty */
400 #endif
401 
402 #if !defined _Noreturn && __STDC_VERSION__ < 201112
403 # if 2 < __GNUC__ + (8 <= __GNUC_MINOR__)
404 #  define _Noreturn __attribute__((__noreturn__))
405 # else
406 #  define _Noreturn
407 # endif
408 #endif
409 
410 #if __STDC_VERSION__ < 199901 && !defined restrict
411 # define restrict /* empty */
412 #endif
413 
414 /*
415 ** Workarounds for compilers/systems.
416 */
417 
418 #ifndef EPOCH_LOCAL
419 # define EPOCH_LOCAL 0
420 #endif
421 #ifndef EPOCH_OFFSET
422 # define EPOCH_OFFSET 0
423 #endif
424 #ifndef RESERVE_STD_EXT_IDS
425 # define RESERVE_STD_EXT_IDS 0
426 #endif
427 
428 /* If standard C identifiers with external linkage (e.g., localtime)
429    are reserved and are not already being renamed anyway, rename them
430    as if compiling with '-Dtime_tz=time_t'.  */
431 #if !defined time_tz && RESERVE_STD_EXT_IDS && USE_LTZ
432 # define time_tz time_t
433 #endif
434 
435 /*
436 ** Compile with -Dtime_tz=T to build the tz package with a private
437 ** time_t type equivalent to T rather than the system-supplied time_t.
438 ** This debugging feature can test unusual design decisions
439 ** (e.g., time_t wider than 'long', or unsigned time_t) even on
440 ** typical platforms.
441 */
442 #if defined time_tz || EPOCH_LOCAL || EPOCH_OFFSET != 0
443 # define TZ_TIME_T 1
444 #else
445 # define TZ_TIME_T 0
446 #endif
447 
448 #if defined LOCALTIME_IMPLEMENTATION && TZ_TIME_T
449 static time_t sys_time(time_t *x) { return time(x); }
450 #endif
451 
452 #if TZ_TIME_T
453 
454 typedef time_tz tz_time_t;
455 
456 # undef  asctime
457 # define asctime tz_asctime
458 # undef  asctime_r
459 # define asctime_r tz_asctime_r
460 # undef  ctime
461 # define ctime tz_ctime
462 # undef  ctime_r
463 # define ctime_r tz_ctime_r
464 # undef  difftime
465 # define difftime tz_difftime
466 # undef  gmtime
467 # define gmtime tz_gmtime
468 # undef  gmtime_r
469 # define gmtime_r tz_gmtime_r
470 # undef  localtime
471 # define localtime tz_localtime
472 # undef  localtime_r
473 # define localtime_r tz_localtime_r
474 # undef  localtime_rz
475 # define localtime_rz tz_localtime_rz
476 # undef  mktime
477 # define mktime tz_mktime
478 # undef  mktime_z
479 # define mktime_z tz_mktime_z
480 # undef  offtime
481 # define offtime tz_offtime
482 # undef  posix2time
483 # define posix2time tz_posix2time
484 # undef  posix2time_z
485 # define posix2time_z tz_posix2time_z
486 # undef  strftime
487 # define strftime tz_strftime
488 # undef  time
489 # define time tz_time
490 # undef  time2posix
491 # define time2posix tz_time2posix
492 # undef  time2posix_z
493 # define time2posix_z tz_time2posix_z
494 # undef  time_t
495 # define time_t tz_time_t
496 # undef  timegm
497 # define timegm tz_timegm
498 # undef  timelocal
499 # define timelocal tz_timelocal
500 # undef  timeoff
501 # define timeoff tz_timeoff
502 # undef  tzalloc
503 # define tzalloc tz_tzalloc
504 # undef  tzfree
505 # define tzfree tz_tzfree
506 # undef  tzset
507 # define tzset tz_tzset
508 # undef  tzsetwall
509 # define tzsetwall tz_tzsetwall
510 # if HAVE_STRFTIME_L
511 #  undef  strftime_l
512 #  define strftime_l tz_strftime_l
513 # endif
514 # if HAVE_TZNAME
515 #  undef  tzname
516 #  define tzname tz_tzname
517 # endif
518 # if USG_COMPAT
519 #  undef  daylight
520 #  define daylight tz_daylight
521 #  undef  timezone
522 #  define timezone tz_timezone
523 # endif
524 # if ALTZONE
525 #  undef  altzone
526 #  define altzone tz_altzone
527 # endif
528 
529 char *asctime(struct tm const *);
530 char *asctime_r(struct tm const *restrict, char *restrict);
531 char *ctime(time_t const *);
532 char *ctime_r(time_t const *, char *);
533 double difftime(time_t, time_t) ATTRIBUTE_CONST;
534 size_t strftime(char *restrict, size_t, char const *restrict,
535 		struct tm const *restrict);
536 # if HAVE_STRFTIME_L
537 size_t strftime_l(char *restrict, size_t, char const *restrict,
538 		  struct tm const *restrict, locale_t);
539 # endif
540 struct tm *gmtime(time_t const *);
541 struct tm *gmtime_r(time_t const *restrict, struct tm *restrict);
542 struct tm *localtime(time_t const *);
543 struct tm *localtime_r(time_t const *restrict, struct tm *restrict);
544 time_t mktime(struct tm *);
545 time_t time(time_t *);
546 void tzset(void);
547 #endif
548 
549 #if !HAVE_DECL_ASCTIME_R && !defined asctime_r
550 extern char *asctime_r(struct tm const *restrict, char *restrict);
551 #endif
552 
553 #ifndef HAVE_DECL_ENVIRON
554 # if defined environ || defined __USE_GNU
555 #  define HAVE_DECL_ENVIRON 1
556 # else
557 #  define HAVE_DECL_ENVIRON 0
558 # endif
559 #endif
560 
561 #if !HAVE_DECL_ENVIRON
562 extern char **environ;
563 #endif
564 
565 #if 2 <= HAVE_TZNAME + (TZ_TIME_T || !HAVE_POSIX_DECLS)
566 extern char *tzname[];
567 #endif
568 #if 2 <= USG_COMPAT + (TZ_TIME_T || !HAVE_POSIX_DECLS)
569 extern long timezone;
570 extern int daylight;
571 #endif
572 #if 2 <= ALTZONE + (TZ_TIME_T || !HAVE_POSIX_DECLS)
573 extern long altzone;
574 #endif
575 
576 /*
577 ** The STD_INSPIRED functions are similar, but most also need
578 ** declarations if time_tz is defined.
579 */
580 
581 #ifdef STD_INSPIRED
582 # if TZ_TIME_T || !defined tzsetwall
583 void tzsetwall(void);
584 # endif
585 # if TZ_TIME_T || !defined offtime
586 struct tm *offtime(time_t const *, long);
587 # endif
588 # if TZ_TIME_T || !defined timegm
589 time_t timegm(struct tm *);
590 # endif
591 # if TZ_TIME_T || !defined timelocal
592 time_t timelocal(struct tm *);
593 # endif
594 # if TZ_TIME_T || !defined timeoff
595 time_t timeoff(struct tm *, long);
596 # endif
597 # if TZ_TIME_T || !defined time2posix
598 time_t time2posix(time_t);
599 # endif
600 # if TZ_TIME_T || !defined posix2time
601 time_t posix2time(time_t);
602 # endif
603 #endif
604 
605 /* Infer TM_ZONE on systems where this information is known, but suppress
606    guessing if NO_TM_ZONE is defined.  Similarly for TM_GMTOFF.  */
607 #if (defined __GLIBC__ \
608      || defined __FreeBSD__ || defined __NetBSD__ || defined __OpenBSD__ \
609      || (defined __APPLE__ && defined __MACH__))
610 # if !defined TM_GMTOFF && !defined NO_TM_GMTOFF
611 #  define TM_GMTOFF tm_gmtoff
612 # endif
613 # if !defined TM_ZONE && !defined NO_TM_ZONE
614 #  define TM_ZONE tm_zone
615 # endif
616 #endif
617 
618 /*
619 ** Define functions that are ABI compatible with NetBSD but have
620 ** better prototypes.  NetBSD 6.1.4 defines a pointer type timezone_t
621 ** and labors under the misconception that 'const timezone_t' is a
622 ** pointer to a constant.  This use of 'const' is ineffective, so it
623 ** is not done here.  What we call 'struct state' NetBSD calls
624 ** 'struct __state', but this is a private name so it doesn't matter.
625 */
626 #ifndef __NetBSD__
627 #if NETBSD_INSPIRED
628 typedef struct state *timezone_t;
629 struct tm *localtime_rz(timezone_t restrict, time_t const *restrict,
630 			struct tm *restrict);
631 time_t mktime_z(timezone_t restrict, struct tm *restrict);
632 timezone_t tzalloc(char const *);
633 void tzfree(timezone_t);
634 # ifdef STD_INSPIRED
635 #  if TZ_TIME_T || !defined posix2time_z
636 time_t posix2time_z(timezone_t __restrict, time_t) ATTRIBUTE_PURE;
637 #  endif
638 #  if TZ_TIME_T || !defined time2posix_z
639 time_t time2posix_z(timezone_t __restrict, time_t) ATTRIBUTE_PURE;
640 #  endif
641 # endif
642 #endif
643 #endif
644 
645 /*
646 ** Finally, some convenience items.
647 */
648 
649 #if HAVE_STDBOOL_H
650 # include <stdbool.h>
651 #else
652 # define true 1
653 # define false 0
654 # define bool int
655 #endif
656 
657 #define TYPE_BIT(type)	(sizeof(type) * CHAR_BIT)
658 #define TYPE_SIGNED(type) (/*CONSTCOND*/((type) -1) < 0)
659 #define TWOS_COMPLEMENT(t) (/*CONSTCOND*/(t) ~ (t) 0 < 0)
660 
661 /* Minimum and maximum of two values.  Use lower case to avoid
662    naming clashes with standard include files.  */
663 #define max(a, b) ((a) > (b) ? (a) : (b))
664 #define min(a, b) ((a) < (b) ? (a) : (b))
665 
666 /* Max and min values of the integer type T, of which only the bottom
667    B bits are used, and where the highest-order used bit is considered
668    to be a sign bit if T is signed.  */
669 #define MAXVAL(t, b) /*LINTED*/					\
670   ((t) (((t) 1 << ((b) - 1 - TYPE_SIGNED(t)))			\
671 	- 1 + ((t) 1 << ((b) - 1 - TYPE_SIGNED(t)))))
672 #define MINVAL(t, b)						\
673   ((t) (TYPE_SIGNED(t) ? - TWOS_COMPLEMENT(t) - MAXVAL(t, b) : 0))
674 
675 /* The extreme time values, assuming no padding.  */
676 #define TIME_T_MIN_NO_PADDING MINVAL(time_t, TYPE_BIT(time_t))
677 #define TIME_T_MAX_NO_PADDING MAXVAL(time_t, TYPE_BIT(time_t))
678 
679 /* The extreme time values.  These are macros, not constants, so that
680    any portability problems occur only when compiling .c files that use
681    the macros, which is safer for applications that need only zdump and zic.
682    This implementation assumes no padding if time_t is signed and
683    either the compiler lacks support for _Generic or time_t is not one
684    of the standard signed integer types.  */
685 #if HAVE_GENERIC
686 # define TIME_T_MIN \
687     _Generic((time_t) 0, \
688 	     signed char: SCHAR_MIN, short: SHRT_MIN, \
689 	     int: INT_MIN, long: LONG_MIN, long long: LLONG_MIN, \
690 	     default: TIME_T_MIN_NO_PADDING)
691 # define TIME_T_MAX \
692     (TYPE_SIGNED(time_t) \
693      ? _Generic((time_t) 0, \
694 		signed char: SCHAR_MAX, short: SHRT_MAX, \
695 		int: INT_MAX, long: LONG_MAX, long long: LLONG_MAX, \
696 		default: TIME_T_MAX_NO_PADDING)			    \
697      : (time_t) -1)
698 #else
699 # define TIME_T_MIN TIME_T_MIN_NO_PADDING
700 # define TIME_T_MAX TIME_T_MAX_NO_PADDING
701 #endif
702 
703 /*
704 ** 302 / 1000 is log10(2.0) rounded up.
705 ** Subtract one for the sign bit if the type is signed;
706 ** add one for integer division truncation;
707 ** add one more for a minus sign if the type is signed.
708 */
709 #define INT_STRLEN_MAXIMUM(type) \
710 	((TYPE_BIT(type) - TYPE_SIGNED(type)) * 302 / 1000 + \
711 	1 + TYPE_SIGNED(type))
712 
713 /*
714 ** INITIALIZE(x)
715 */
716 
717 #if defined(__GNUC__) || defined(__lint__)
718 # define INITIALIZE(x)	((x) = 0)
719 #else
720 # define INITIALIZE(x)
721 #endif
722 
723 /* Whether memory access must strictly follow the C standard.
724    If 0, it's OK to read uninitialized storage so long as the value is
725    not relied upon.  Defining it to 0 lets mktime access parts of
726    struct tm that might be uninitialized, as a heuristic when the
727    standard doesn't say what to return and when tm_gmtoff can help
728    mktime likely infer a better value.  */
729 #ifndef UNINIT_TRAP
730 # define UNINIT_TRAP 0
731 #endif
732 
733 #ifdef DEBUG
734 # define UNREACHABLE() abort()
735 #elif 4 < __GNUC__ + (5 <= __GNUC_MINOR__)
736 # define UNREACHABLE() __builtin_unreachable()
737 #elif defined __has_builtin
738 # if __has_builtin(__builtin_unreachable)
739 #  define UNREACHABLE() __builtin_unreachable()
740 # endif
741 #endif
742 #ifndef UNREACHABLE
743 # define UNREACHABLE() ((void) 0)
744 #endif
745 
746 /*
747 ** For the benefit of GNU folk...
748 ** '_(MSGID)' uses the current locale's message library string for MSGID.
749 ** The default is to use gettext if available, and use MSGID otherwise.
750 */
751 
752 #if HAVE_GETTEXT
753 #define _(msgid) gettext(msgid)
754 #else /* !HAVE_GETTEXT */
755 #define _(msgid) msgid
756 #endif /* !HAVE_GETTEXT */
757 
758 #if !defined TZ_DOMAIN && defined HAVE_GETTEXT
759 # define TZ_DOMAIN "tz"
760 #endif
761 
762 #if HAVE_INCOMPATIBLE_CTIME_R
763 #undef asctime_r
764 #undef ctime_r
765 char *asctime_r(struct tm const *, char *);
766 char *ctime_r(time_t const *, char *);
767 #endif /* HAVE_INCOMPATIBLE_CTIME_R */
768 
769 /* Handy macros that are independent of tzfile implementation.  */
770 
771 #ifndef SECSPERMIN
772 enum {
773   SECSPERMIN = 60,
774   MINSPERHOUR = 60,
775   SECSPERHOUR = SECSPERMIN * MINSPERHOUR,
776   HOURSPERDAY = 24,
777   DAYSPERWEEK = 7,
778   DAYSPERNYEAR = 365,
779   DAYSPERLYEAR = DAYSPERNYEAR + 1,
780   MONSPERYEAR = 12,
781   YEARSPERREPEAT = 400	/* years before a Gregorian repeat */
782 };
783 #endif
784 
785 #define SECSPERDAY	((int_fast32_t) SECSPERHOUR * HOURSPERDAY)
786 
787 #define DAYSPERREPEAT		((int_fast32_t) 400 * 365 + 100 - 4 + 1)
788 #define SECSPERREPEAT		((int_fast64_t) DAYSPERREPEAT * SECSPERDAY)
789 #define AVGSECSPERYEAR		(SECSPERREPEAT / YEARSPERREPEAT)
790 
791 #ifndef TM_SUNDAY
792 enum {
793   TM_SUNDAY,
794   TM_MONDAY,
795   TM_TUESDAY,
796   TM_WEDNESDAY,
797   TM_THURSDAY,
798   TM_FRIDAY,
799   TM_SATURDAY
800 };
801 #endif
802 
803 #ifndef TM_JANUARY
804 enum {
805   TM_JANUARY,
806   TM_FEBRUARY,
807   TM_MARCH,
808   TM_APRIL,
809   TM_MAY,
810   TM_JUNE,
811   TM_JULY,
812   TM_AUGUST,
813   TM_SEPTEMBER,
814   TM_OCTOBER,
815   TM_NOVEMBER,
816   TM_DECEMBER
817 };
818 #endif
819 
820 #ifndef TM_YEAR_BASE
821 enum {
822   TM_YEAR_BASE = 1900,
823   TM_WDAY_BASE = TM_MONDAY,
824   EPOCH_YEAR = 1970,
825   EPOCH_WDAY = TM_THURSDAY
826 };
827 #endif
828 
829 #define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
830 
831 /*
832 ** Since everything in isleap is modulo 400 (or a factor of 400), we know that
833 **	isleap(y) == isleap(y % 400)
834 ** and so
835 **	isleap(a + b) == isleap((a + b) % 400)
836 ** or
837 **	isleap(a + b) == isleap(a % 400 + b % 400)
838 ** This is true even if % means modulo rather than Fortran remainder
839 ** (which is allowed by C89 but not by C99 or later).
840 ** We use this to avoid addition overflow problems.
841 */
842 
843 #define isleap_sum(a, b)	isleap((a) % 400 + (b) % 400)
844 
845 #ifdef _LIBC
846 #include "reentrant.h"
847 extern struct __state *__lclptr;
848 #if defined(__LIBC12_SOURCE__)
849 #define tzset_unlocked __tzset_unlocked
850 #else
851 #define tzset_unlocked __tzset_unlocked50
852 #endif
853 
854 void tzset_unlocked(void);
855 #ifdef _REENTRANT
856 extern rwlock_t __lcl_lock;
857 #endif
858 #endif
859 
860 #endif /* !defined PRIVATE_H */
861