diff options
Diffstat (limited to 'xdelta1/libedsio/maketime.c')
-rw-r--r-- | xdelta1/libedsio/maketime.c | 391 |
1 files changed, 0 insertions, 391 deletions
diff --git a/xdelta1/libedsio/maketime.c b/xdelta1/libedsio/maketime.c deleted file mode 100644 index 5feddae..0000000 --- a/xdelta1/libedsio/maketime.c +++ /dev/null | |||
@@ -1,391 +0,0 @@ | |||
1 | /* Convert struct partime into time_t. */ | ||
2 | |||
3 | /* Copyright 1992, 1993, 1994, 1995, 1997 Paul Eggert | ||
4 | Distributed under license by the Free Software Foundation, Inc. | ||
5 | |||
6 | This file is part of RCS. | ||
7 | |||
8 | RCS is free software; you can redistribute it and/or modify | ||
9 | it under the terms of the GNU General Public License as published by | ||
10 | the Free Software Foundation; either version 2, or (at your option) | ||
11 | any later version. | ||
12 | |||
13 | RCS is distributed in the hope that it will be useful, | ||
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | GNU General Public License for more details. | ||
17 | |||
18 | You should have received a copy of the GNU General Public License | ||
19 | along with RCS; see the file COPYING. | ||
20 | If not, write to the Free Software Foundation, | ||
21 | 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
22 | |||
23 | Report problems and direct all questions to: | ||
24 | |||
25 | rcs-bugs@cs.purdue.edu | ||
26 | |||
27 | */ | ||
28 | |||
29 | #if has_conf_h | ||
30 | # include <conf.h> | ||
31 | #else | ||
32 | # if HAVE_CONFIG_H | ||
33 | # include <config.h> | ||
34 | # else | ||
35 | # ifndef __STDC__ | ||
36 | # define const | ||
37 | # endif | ||
38 | # endif | ||
39 | /* MIPS RISCOS4.52 defines time_t in <sys/types.h> not <time.h>. */ | ||
40 | # include <sys/types.h> | ||
41 | # if HAVE_LIMITS_H | ||
42 | # include <limits.h> | ||
43 | # endif | ||
44 | # ifndef LONG_MIN | ||
45 | # define LONG_MIN (-1-2147483647L) | ||
46 | # endif | ||
47 | # if STDC_HEADERS | ||
48 | # include <stdlib.h> | ||
49 | # endif | ||
50 | # include <time.h> | ||
51 | # ifdef __STDC__ | ||
52 | # define P(x) x | ||
53 | # else | ||
54 | # define P(x) () | ||
55 | # endif | ||
56 | #endif | ||
57 | |||
58 | #include <partime.h> | ||
59 | #include <maketime.h> | ||
60 | |||
61 | char const maketId[] = | ||
62 | "$Id: maketime.c 1.1 Sun, 28 Jan 2007 10:02:26 -0800 jmacd $"; | ||
63 | |||
64 | static int isleap P ((int)); | ||
65 | static int month_days P ((struct tm const *)); | ||
66 | static time_t maketime P ((struct partime const *, time_t)); | ||
67 | |||
68 | /* For maximum portability, use only localtime and gmtime. | ||
69 | Make no assumptions about the time_t epoch or the range of time_t values. | ||
70 | Avoid mktime because it's not universal and because there's no easy, | ||
71 | portable way for mktime to yield the inverse of gmtime. */ | ||
72 | |||
73 | #define TM_YEAR_ORIGIN 1900 | ||
74 | |||
75 | static int | ||
76 | isleap (y) | ||
77 | int y; | ||
78 | { | ||
79 | return (y & 3) == 0 && (y % 100 != 0 || y % 400 == 0); | ||
80 | } | ||
81 | |||
82 | /* days in year before start of months 0-12 */ | ||
83 | static int const month_yday[] = | ||
84 | { | ||
85 | 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 | ||
86 | }; | ||
87 | |||
88 | /* Yield the number of days in TM's month. */ | ||
89 | static int | ||
90 | month_days (tm) | ||
91 | struct tm const *tm; | ||
92 | { | ||
93 | int m = tm->tm_mon; | ||
94 | return (month_yday[m + 1] - month_yday[m] | ||
95 | + (m == 1 && isleap (tm->tm_year + TM_YEAR_ORIGIN))); | ||
96 | } | ||
97 | |||
98 | /* Convert UNIXTIME to struct tm form. | ||
99 | Use gmtime if available and if !LOCALZONE, localtime otherwise. */ | ||
100 | struct tm * | ||
101 | time2tm (unixtime, localzone) | ||
102 | time_t unixtime; | ||
103 | int localzone; | ||
104 | { | ||
105 | struct tm *tm; | ||
106 | #ifdef TZ_is_unset | ||
107 | static char const *TZ; | ||
108 | if (!TZ && !(TZ = getenv ("TZ"))) | ||
109 | TZ_is_unset ("The TZ environment variable is not set; please set it to your timezone"); | ||
110 | #endif | ||
111 | if (localzone || !(tm = gmtime (&unixtime))) | ||
112 | tm = localtime (&unixtime); | ||
113 | return tm; | ||
114 | } | ||
115 | |||
116 | /* Yield A - B, measured in seconds. */ | ||
117 | time_t | ||
118 | difftm (a, b) | ||
119 | struct tm const *a; | ||
120 | struct tm const *b; | ||
121 | { | ||
122 | int ay = a->tm_year + (TM_YEAR_ORIGIN - 1); | ||
123 | int by = b->tm_year + (TM_YEAR_ORIGIN - 1); | ||
124 | int ac = ay / 100 - (ay % 100 < 0); | ||
125 | int bc = by / 100 - (by % 100 < 0); | ||
126 | int difference_in_day_of_year = a->tm_yday - b->tm_yday; | ||
127 | int intervening_leap_days = (((ay >> 2) - (by >> 2)) | ||
128 | - (ac - bc) | ||
129 | + ((ac >> 2) - (bc >> 2))); | ||
130 | time_t difference_in_years = ay - by; | ||
131 | time_t difference_in_days | ||
132 | = (difference_in_years * 365 | ||
133 | + (intervening_leap_days + difference_in_day_of_year)); | ||
134 | return (((((difference_in_days * 24 | ||
135 | + (a->tm_hour - b->tm_hour)) | ||
136 | * 60) | ||
137 | + (a->tm_min - b->tm_min)) | ||
138 | * 60) | ||
139 | + (a->tm_sec - b->tm_sec)); | ||
140 | } | ||
141 | |||
142 | /* | ||
143 | * Adjust time T by adding SECONDS. SECONDS must be at most 24 hours' worth. | ||
144 | * Adjust only T's year, mon, mday, hour, min and sec members; | ||
145 | * plus adjust wday if it is defined. | ||
146 | */ | ||
147 | void | ||
148 | adjzone (t, seconds) | ||
149 | register struct tm *t; | ||
150 | long seconds; | ||
151 | { | ||
152 | /* | ||
153 | * This code can be off by a second if SECONDS is not a multiple of 60, | ||
154 | * if T is local time, and if a leap second happens during this minute. | ||
155 | * But this bug has never occurred, and most likely will not ever occur. | ||
156 | * Liberia, the last country for which SECONDS % 60 was nonzero, | ||
157 | * switched to UTC in May 1972; the first leap second was in June 1972. | ||
158 | */ | ||
159 | int leap_second = t->tm_sec == 60; | ||
160 | long sec = seconds + (t->tm_sec - leap_second); | ||
161 | if (sec < 0) | ||
162 | { | ||
163 | if ((t->tm_min -= (59 - sec) / 60) < 0) | ||
164 | { | ||
165 | if ((t->tm_hour -= (59 - t->tm_min) / 60) < 0) | ||
166 | { | ||
167 | t->tm_hour += 24; | ||
168 | if (TM_DEFINED (t->tm_wday) && --t->tm_wday < 0) | ||
169 | t->tm_wday = 6; | ||
170 | if (--t->tm_mday <= 0) | ||
171 | { | ||
172 | if (--t->tm_mon < 0) | ||
173 | { | ||
174 | --t->tm_year; | ||
175 | t->tm_mon = 11; | ||
176 | } | ||
177 | t->tm_mday = month_days (t); | ||
178 | } | ||
179 | } | ||
180 | t->tm_min += 24 * 60; | ||
181 | } | ||
182 | sec += 24L * 60 * 60; | ||
183 | } | ||
184 | else if (60 <= (t->tm_min += sec / 60)) | ||
185 | if (24 <= (t->tm_hour += t->tm_min / 60)) | ||
186 | { | ||
187 | t->tm_hour -= 24; | ||
188 | if (TM_DEFINED (t->tm_wday) && ++t->tm_wday == 7) | ||
189 | t->tm_wday = 0; | ||
190 | if (month_days (t) < ++t->tm_mday) | ||
191 | { | ||
192 | if (11 < ++t->tm_mon) | ||
193 | { | ||
194 | ++t->tm_year; | ||
195 | t->tm_mon = 0; | ||
196 | } | ||
197 | t->tm_mday = 1; | ||
198 | } | ||
199 | } | ||
200 | t->tm_min %= 60; | ||
201 | t->tm_sec = (int) (sec % 60) + leap_second; | ||
202 | } | ||
203 | |||
204 | /* | ||
205 | * Convert TM to time_t, using localtime if LOCALZONE and gmtime otherwise. | ||
206 | * Use only TM's year, mon, mday, hour, min, and sec members. | ||
207 | * Ignore TM's old tm_yday and tm_wday, but fill in their correct values. | ||
208 | * Yield -1 on failure (e.g. a member out of range). | ||
209 | * Posix 1003.1-1990 doesn't allow leap seconds, but some implementations | ||
210 | * have them anyway, so allow them if localtime/gmtime does. | ||
211 | */ | ||
212 | time_t | ||
213 | tm2time (tm, localzone) | ||
214 | struct tm *tm; | ||
215 | int localzone; | ||
216 | { | ||
217 | /* Cache the most recent t,tm pairs; 1 for gmtime, 1 for localtime. */ | ||
218 | static time_t t_cache[2]; | ||
219 | static struct tm tm_cache[2]; | ||
220 | |||
221 | time_t d, gt; | ||
222 | struct tm const *gtm; | ||
223 | /* | ||
224 | * The maximum number of iterations should be enough to handle any | ||
225 | * combinations of leap seconds, time zone rule changes, and solar time. | ||
226 | * 4 is probably enough; we use a bigger number just to be safe. | ||
227 | */ | ||
228 | int remaining_tries = 8; | ||
229 | |||
230 | /* Avoid subscript errors. */ | ||
231 | if (12 <= (unsigned) tm->tm_mon) | ||
232 | return -1; | ||
233 | |||
234 | tm->tm_yday = month_yday[tm->tm_mon] + tm->tm_mday | ||
235 | - (tm->tm_mon < 2 || !isleap (tm->tm_year + TM_YEAR_ORIGIN)); | ||
236 | |||
237 | /* Make a first guess. */ | ||
238 | gt = t_cache[localzone]; | ||
239 | gtm = gt ? &tm_cache[localzone] : time2tm (gt, localzone); | ||
240 | |||
241 | /* Repeatedly use the error from the guess to improve the guess. */ | ||
242 | while ((d = difftm (tm, gtm)) != 0) | ||
243 | { | ||
244 | if (--remaining_tries == 0) | ||
245 | return -1; | ||
246 | gt += d; | ||
247 | gtm = time2tm (gt, localzone); | ||
248 | } | ||
249 | |||
250 | /* | ||
251 | * Check that the guess actually matches; | ||
252 | * overflow can cause difftm to yield 0 even on differing times, | ||
253 | * or tm may have members out of range (e.g. bad leap seconds). | ||
254 | */ | ||
255 | #define TM_DIFFER(a,b) \ | ||
256 | ( \ | ||
257 | ((a)->tm_year ^ (b)->tm_year) | \ | ||
258 | ((a)->tm_mon ^ (b)->tm_mon) | \ | ||
259 | ((a)->tm_mday ^ (b)->tm_mday) | \ | ||
260 | ((a)->tm_hour ^ (b)->tm_hour) | \ | ||
261 | ((a)->tm_min ^ (b)->tm_min) | \ | ||
262 | ((a)->tm_sec ^ (b)->tm_sec) \ | ||
263 | ) | ||
264 | if (TM_DIFFER (tm, gtm)) | ||
265 | { | ||
266 | /* | ||
267 | * If gt is a leap second, try gt+1; if it is one greater than | ||
268 | * a leap second, try gt-1; otherwise, it doesn't matter. | ||
269 | * Leap seconds always fall at month end. | ||
270 | */ | ||
271 | int yd = tm->tm_year - gtm->tm_year; | ||
272 | gt += yd + (yd ? 0 : tm->tm_mon - gtm->tm_mon); | ||
273 | gtm = time2tm (gt, localzone); | ||
274 | if (TM_DIFFER (tm, gtm)) | ||
275 | return -1; | ||
276 | } | ||
277 | t_cache[localzone] = gt; | ||
278 | tm_cache[localzone] = *gtm; | ||
279 | |||
280 | tm->tm_wday = gtm->tm_wday; | ||
281 | return gt; | ||
282 | } | ||
283 | |||
284 | /* | ||
285 | * Check *PT and convert it to time_t. | ||
286 | * If it is incompletely specified, use DEFAULT_TIME to fill it out. | ||
287 | * Use localtime if PT->zone is the special value TM_LOCAL_ZONE. | ||
288 | * Yield -1 on failure. | ||
289 | * ISO 8601 day-of-year and week numbers are not yet supported. | ||
290 | */ | ||
291 | static time_t | ||
292 | maketime (pt, default_time) | ||
293 | struct partime const *pt; | ||
294 | time_t default_time; | ||
295 | { | ||
296 | int localzone, wday; | ||
297 | struct tm tm; | ||
298 | struct tm *tm0 = 0; | ||
299 | time_t r; | ||
300 | |||
301 | tm0 = 0; /* Keep gcc -Wall happy. */ | ||
302 | localzone = pt->zone == TM_LOCAL_ZONE; | ||
303 | |||
304 | tm = pt->tm; | ||
305 | |||
306 | if (TM_DEFINED (pt->ymodulus) || !TM_DEFINED (tm.tm_year)) | ||
307 | { | ||
308 | /* Get tm corresponding to default time. */ | ||
309 | tm0 = time2tm (default_time, localzone); | ||
310 | if (!localzone) | ||
311 | adjzone (tm0, pt->zone); | ||
312 | } | ||
313 | |||
314 | if (TM_DEFINED (pt->ymodulus)) | ||
315 | tm.tm_year += | ||
316 | (tm0->tm_year + TM_YEAR_ORIGIN) / pt->ymodulus * pt->ymodulus; | ||
317 | else if (!TM_DEFINED (tm.tm_year)) | ||
318 | { | ||
319 | /* Set default year, month, day from current time. */ | ||
320 | tm.tm_year = tm0->tm_year + TM_YEAR_ORIGIN; | ||
321 | if (!TM_DEFINED (tm.tm_mon)) | ||
322 | { | ||
323 | tm.tm_mon = tm0->tm_mon; | ||
324 | if (!TM_DEFINED (tm.tm_mday)) | ||
325 | tm.tm_mday = tm0->tm_mday; | ||
326 | } | ||
327 | } | ||
328 | |||
329 | /* Convert from partime year (Gregorian) to Posix year. */ | ||
330 | tm.tm_year -= TM_YEAR_ORIGIN; | ||
331 | |||
332 | /* Set remaining default fields to be their minimum values. */ | ||
333 | if (!TM_DEFINED (tm.tm_mon)) | ||
334 | tm.tm_mon = 0; | ||
335 | if (!TM_DEFINED (tm.tm_mday)) | ||
336 | tm.tm_mday = 1; | ||
337 | if (!TM_DEFINED (tm.tm_hour)) | ||
338 | tm.tm_hour = 0; | ||
339 | if (!TM_DEFINED (tm.tm_min)) | ||
340 | tm.tm_min = 0; | ||
341 | if (!TM_DEFINED (tm.tm_sec)) | ||
342 | tm.tm_sec = 0; | ||
343 | |||
344 | if (!localzone) | ||
345 | adjzone (&tm, -pt->zone); | ||
346 | wday = tm.tm_wday; | ||
347 | |||
348 | /* Convert and fill in the rest of the tm. */ | ||
349 | r = tm2time (&tm, localzone); | ||
350 | |||
351 | /* Check weekday. */ | ||
352 | if (r != -1 && TM_DEFINED (wday) && wday != tm.tm_wday) | ||
353 | return -1; | ||
354 | |||
355 | return r; | ||
356 | } | ||
357 | |||
358 | /* Parse a free-format date in SOURCE, yielding a Unix format time. */ | ||
359 | time_t | ||
360 | str2time (source, default_time, default_zone) | ||
361 | char const *source; | ||
362 | time_t default_time; | ||
363 | long default_zone; | ||
364 | { | ||
365 | struct partime pt; | ||
366 | |||
367 | if (*partime (source, &pt)) | ||
368 | return -1; | ||
369 | if (pt.zone == TM_UNDEFINED_ZONE) | ||
370 | pt.zone = default_zone; | ||
371 | return maketime (&pt, default_time); | ||
372 | } | ||
373 | |||
374 | #if TEST | ||
375 | #include <stdio.h> | ||
376 | int | ||
377 | main (argc, argv) | ||
378 | int argc; | ||
379 | char **argv; | ||
380 | { | ||
381 | time_t default_time = time ((time_t *) 0); | ||
382 | long default_zone = argv[1] ? atol (argv[1]) : 0; | ||
383 | char buf[1000]; | ||
384 | while (fgets (buf, sizeof (buf), stdin)) | ||
385 | { | ||
386 | time_t t = str2time (buf, default_time, default_zone); | ||
387 | printf ("%s", asctime (gmtime (&t))); | ||
388 | } | ||
389 | return 0; | ||
390 | } | ||
391 | #endif | ||