]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - contrib/unbound/compat/gmtime_r.c
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / contrib / unbound / compat / gmtime_r.c
1 /*
2  * Taken from FreeBSD src / lib / libc / stdtime / localtime.c 1.43 revision.
3  * localtime.c 7.78.
4  * tzfile.h 1.8
5  * adapted to be replacement gmtime_r.
6  */
7 #include "config.h"
8
9 #ifdef HAVE_TIME_H
10 #include <time.h>
11 #endif
12
13 #define MONSPERYEAR 12
14 #define DAYSPERNYEAR 365
15 #define DAYSPERLYEAR 366
16 #define SECSPERMIN 60
17 #define SECSPERHOUR (60*60)
18 #define SECSPERDAY (24*60*60)
19 #define DAYSPERWEEK 7
20 #define TM_SUNDAY       0
21 #define TM_MONDAY       1
22 #define TM_TUESDAY      2
23 #define TM_WEDNESDAY    3
24 #define TM_THURSDAY     4
25 #define TM_FRIDAY       5
26 #define TM_SATURDAY     6
27
28 #define TM_YEAR_BASE    1900
29
30 #define EPOCH_YEAR      1970
31 #define EPOCH_WDAY      TM_THURSDAY
32
33 #define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
34
35 static const int        mon_lengths[2][MONSPERYEAR] = {
36         { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
37         { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
38 };
39
40 static const int        year_lengths[2] = {
41         DAYSPERNYEAR, DAYSPERLYEAR
42 };
43
44 static void
45 timesub(timep, offset, tmp)
46 const time_t * const                    timep;
47 const long                              offset;
48 struct tm * const               tmp;
49 {
50         long                    days;
51         long                    rem;
52         long                    y;
53         int                     yleap;
54         const int *             ip;
55
56         days = *timep / SECSPERDAY;
57         rem = *timep % SECSPERDAY;
58         rem += (offset);
59         while (rem < 0) {
60                 rem += SECSPERDAY;
61                 --days;
62         }
63         while (rem >= SECSPERDAY) {
64                 rem -= SECSPERDAY;
65                 ++days;
66         }
67         tmp->tm_hour = (int) (rem / SECSPERHOUR);
68         rem = rem % SECSPERHOUR;
69         tmp->tm_min = (int) (rem / SECSPERMIN);
70         /*
71         ** A positive leap second requires a special
72         ** representation.  This uses "... ??:59:60" et seq.
73         */
74         tmp->tm_sec = (int) (rem % SECSPERMIN) ;
75         tmp->tm_wday = (int) ((EPOCH_WDAY + days) % DAYSPERWEEK);
76         if (tmp->tm_wday < 0)
77                 tmp->tm_wday += DAYSPERWEEK;
78         y = EPOCH_YEAR;
79 #define LEAPS_THRU_END_OF(y)    ((y) / 4 - (y) / 100 + (y) / 400)
80         while (days < 0 || days >= (long) year_lengths[yleap = isleap(y)]) {
81                 long    newy;
82
83                 newy = y + days / DAYSPERNYEAR;
84                 if (days < 0)
85                         --newy;
86                 days -= (newy - y) * DAYSPERNYEAR +
87                         LEAPS_THRU_END_OF(newy - 1) -
88                         LEAPS_THRU_END_OF(y - 1);
89                 y = newy;
90         }
91         tmp->tm_year = y - TM_YEAR_BASE;
92         tmp->tm_yday = (int) days;
93         ip = mon_lengths[yleap];
94         for (tmp->tm_mon = 0; days >= (long) ip[tmp->tm_mon]; ++(tmp->tm_mon))
95                 days = days - (long) ip[tmp->tm_mon];
96         tmp->tm_mday = (int) (days + 1);
97         tmp->tm_isdst = 0;
98 }
99
100 /*
101 * Re-entrant version of gmtime.
102 */
103 struct tm * gmtime_r(const time_t* timep, struct tm *tm)
104 {
105         timesub(timep, 0L, tm);
106         return tm;
107 }