comparison src/mktime.c @ 26088:b7aa6ac26872

Add support for large files, 64-bit Solaris, system locale codings. * Makefile.in (emacs): Set the LC_ALL environment variable to "C" when dumping, so that the dumped Emacs doesn't have stray locale info. (dired.o): Depend on systime.h. (editfns.o): Depend on coding.h. * alloc.c, buffer.c, callproc.c, ccl.c, charset.c, coding.c, data.c, dispnew.c, editfns.c, emacs.c, filelock.c, floatfns.c, hftctl.c, keyboard.c, process.c, sysdep.c, unexelf.c, unexhp9k800.c, unexsunos4.c, vmsfns.c, vmsgmalloc.c, w32faces.c, w32menu.c, w32term.c, w32xfns.c, xfaces.c, xfns.c, xmenu.c, xterm.c: Include <config.h> before any system include files. * alloc.c, buffer.c, ccl.c, data.c, editfns.c, emacs.c, eval.c, fileio.c, filelock.c, frame.c, insdel.c, keymap.c, lread.c, m/alpha.h, print.c, search.c, sysdep.c, xdisp.c, xfaces.c, xfns.c, xmenu.c, xterm.c: Do not include <stdlib.h>, as <config.h> does this now. * callproc.c (Fcall_process): Synchronize messages locale before invoking strerror. Decode resulting string with locale-coding-system. * coding.c (Vlocale_coding_system): New var. (syms_of_coding): Adjust to above change. (emacs_strerror): New function. * coding.h (emacs_strerror, Vlocale_coding_system): New decls. * config.in (HAVE_STDIO_EXT_H, HAVE_TM_GMTOFF, HAVE___FPENDING, HAVE_FTELLO, HAVE_GETLOADAVG, HAVE_MBLEN, HAVE_MBRLEN, HAVE_STRSIGNAL): New macros. (BITS_PER_LONG): Default to 64 if _LP64 is defined. <stdlib.h>: Include if HAVE_STDLIB_H is defined and NOT_C_CODE isn't. * dired.c: Include "systime.h". (Ffile_attributes): Do not cast s.st_size to int; this loses information if int is 32 bits but st_size and EMACS_INT are larger. Treat large device numbers like large inode numbers. * dispnew.c (PENDING_OUTPUT_COUNT): Use __fpending if available. * editfns.c: Include coding.h. (emacs_strftime): Remove decl. (emacs_strftimeu): New decl. (emacs_memftimeu): Renamed from emacs_memftime; new arg UT. Use emacs_strftimeu instead of emacs_strftime. (Fformat_time_string): Convert format string using Vlocale_coding_system, and convert result back. Synchronize time locale before invoking lower level function. Invoke emacs_memftimeu, passing ut, instead of emacs_memftime. * emacs.c: Include <locale.h> if HAVE_SETLOCALE is defined. (Vmessages_locale, Vprevious_messages_locale, Vtime_locale, Vprevious_time_locale): New variables. (main): Invoke setlocale early, so that initial error messages are localized properly. But skip locale-setting if LC_ALL is "C". Fix up locale when it's safe to do so. (fixup_locale): Moved here from xterm.c. (synchronize_locale, synchronize_time_locale, synchronize_messages_locale): New functions. (syms_of_emacs): Accommodate above changes. * fileio.c (report_file_error): Convert strerror output according to Vlocale_coding_system. (Finsert_file_contents): Check for arithmetic overflow in computations that depend on file size. Report IO errors with emacs_strerror, not strerror. * fns.c (Fgethash): Declare dflt parameter. * gmalloc.c: Do not define const to nothing if HAVE_CONFIG_H is defined; that's config.h's job. * lisp.h (EMACS_INT, BITS_PER_EMACS_INT, EMACS_UINT): If _LP64, default these values to long, BITS_PER_LONG, and unsigned long. (VALBITS, MARKBIT, XINT): Do not assume 32-bit EMACS_INT. (PNTR_COMPARISON_TYPE): Default to EMACS_UINT, not to unsigned int. (code_convert_string_norecord, fixup_locale, synchronize_messages_locale, synchronize_time_locale, emacs_open, emacs_close, emacs_read, emacs_write): New decls. All Emacs callers of open, close, read, write changed to use emacs_open, emacs_close, emacs_read, emacs_write. * lread.c (file_offset, file_tell): New macros. All uses of ftell changed to file_tell. (saved_doc_string_position, prev_saved_doc_string_position): Now of type file_offset. (init_lread): Do not fix locale here; fixup_locale now does this. * m/amdahl.h, s/usg5-4.h: (NSIG): Remove. (NSIG_MINIMUM): New macro. * m/cydra5.h, m/dpx2.h, m/mips.h, m/pfa50.h, m/sps7.h, m/stride.h, m/ustation.h, s/gnu-linux.h, s/hpux.h, s/iris3-5.h, s/iris3-6.h, s/umips.h, s/usg5-4.h: (SIGIO): Do not undef. (BROKEN_SIGIO): New macro. * m/ustation.h: (SIGTSTP): Do not undef. (BROKEN_SIGTSTP): New macro. * s/gnu-linux.h: (SIGPOLL, SIGURG): Do not undef. (BROKEN_SIGPOLL, BROKEN_SIGURG): New macros. * s/ptx4.h: (SIGINFO): Do not undef. (BROKEN_SIGINFO): New macros. * m/delta.h, s/ptx.h, s/template.h: Doc fix. * mktime.c, strftime.c: Update to glibc 2.1.2 version, with some Emacs-related changes merged. * print.c (float_to_string): Prepend "-" to representation of a NaN if the NaN is negative. * process.c (sys_siglist): Omit if HAVE_STRSIGNAL. (wait_reading_process_input): Use emacs_strerror, not strerror. * process.c (status_message, sigchld_handler): Synchronize locale, then use strsignal istead of sys_siglist. * w32proc.c (sys_wait): Likewise. * s/aix3-1.h, s/bsd4-1.h, s/dgux.h, s/gnu-linux.h, s/hiuxmpp.h, s/hpux.h, s/iris3-5.h, s/iris3-6.h, s/irix3-3.h, s/osf1.h, s/rtu.h, s/sunos4-1.h, s/unipl5-0.h, s/unipl5-2.h, s/usg5-0.h, s/usg5-2-2.h, s/usg5-2.h, s/usg5-3.h, s/xenix.h: (open, close, read, write, INTERRUPTIBLE_OPEN, INTERRUPTIBLE_CLOSE, INTERRUPTIBLE_IO): Remove. * s/sol2-5.h (_LARGEFILE_SOURCE, _FILE_OFFSET_BITS): New macros. * sysdep.c (sys_read, sys_write, read, write, sys_close, close, sys_open, open): Remove. (emacs_open, emacs_close, emacs_read, emacs_write): Always define; the old INTERRUPTIBLE_OPEN, INTERRUPTIBLE_CLOSE, and INTERRUPTIBLE_IO macros are no longer used. (emacs_open): Renamed from sys_open. Merge BSD4_1 version. (emacs_close): Renamed from sys_close. (emacs_read): Renamed from sys_read. (emacs_write): Renamed from sys_write. (sys_siglist): Do not declare if HAVE_STRSIGNAL. (dup2): Do not print error on failure; the real dup2 doesn't. (strsignal): New function, defined if !HAVE_STRSIGNAL. * syssignal.h (SIGINFO): Undef if defined and if BROKEN_SIGINFO is defined. (SIGIO, SIGPOLL, SIGTSTP, SIGURG): Likewise. (NSIG): If less than NSIG_MINIMUM, define to NSIG_MINIMUM. (strsignal): Declare if !HAVE_STRSIGNAL. * unexelf.c (ElfBitsW, ELFSIZE, ElfExpandBitsW): New macros. (ElfW): Define in terms of ElfExpandBitsW. * w32proc.c (sys_siglist): Remove decl. * xdisp.c (decode_mode_spec): 3rd arg is int, not char, to comply with ANSI C. (display_string): Declare face_string_pos arg. * xfns.c (Fx_show_tip): Declare timeout param. * xterm.c: No need to include locale.h. (x_alloc_lighter_color, x_setup_relief_color): Pass arg as double, not float, for compatibility with ANSI C. (fixup_locale): Move to emacs.c. (x_term_init): Do not setlocale or fixup locale; the main program does this now.
author Paul Eggert <eggert@twinsun.com>
date Tue, 19 Oct 1999 07:25:11 +0000
parents c8c409640bf3
children 7568310ea7d6
comparison
equal deleted inserted replaced
26087:e0d966fb548f 26088:b7aa6ac26872
1 /* Copyright (C) 1993, 94, 95, 96, 97, 98 Free Software Foundation, Inc. 1 /* Convert a `struct tm' to a time_t value.
2 Copyright (C) 1993, 94, 95, 96, 97, 98, 99 Free Software Foundation, Inc.
2 Contributed by Paul Eggert (eggert@twinsun.com). 3 Contributed by Paul Eggert (eggert@twinsun.com).
3 4
4 NOTE: The canonical source of this file is maintained with the GNU C Library. 5 NOTE: The canonical source of this file is maintained with the GNU C Library.
5 Bugs can be reported to bug-glibc@gnu.org. 6 Bugs can be reported to bug-glibc@gnu.org.
6 7
25 26
26 #ifdef HAVE_CONFIG_H 27 #ifdef HAVE_CONFIG_H
27 # include <config.h> 28 # include <config.h>
28 #endif 29 #endif
29 30
30 /* Some systems need this in order to declare localtime_r properly. */
31 #ifndef _REENTRANT
32 # define _REENTRANT 1
33 #endif
34
35 #ifdef _LIBC 31 #ifdef _LIBC
36 # define HAVE_LIMITS_H 1 32 # define HAVE_LIMITS_H 1
37 # define HAVE_LOCALTIME_R 1
38 # define STDC_HEADERS 1 33 # define STDC_HEADERS 1
39 #endif 34 #endif
40 35
41 /* Assume that leap seconds are possible, unless told otherwise. 36 /* Assume that leap seconds are possible, unless told otherwise.
42 If the host has a `zic' command with a `-L leapsecondfilename' option, 37 If the host has a `zic' command with a `-L leapsecondfilename' option,
60 /* Make it work even if the system's libc has its own mktime routine. */ 55 /* Make it work even if the system's libc has its own mktime routine. */
61 # define mktime my_mktime 56 # define mktime my_mktime
62 #endif /* DEBUG */ 57 #endif /* DEBUG */
63 58
64 #ifndef __P 59 #ifndef __P
65 # if defined (__GNUC__) || (defined (__STDC__) && __STDC__) 60 # if defined __GNUC__ || (defined __STDC__ && __STDC__)
66 # define __P(args) args 61 # define __P(args) args
67 # else 62 # else
68 # define __P(args) () 63 # define __P(args) ()
69 # endif /* GCC. */ 64 # endif /* GCC. */
70 #endif /* Not __P. */ 65 #endif /* Not __P. */
112 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }, 107 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
113 /* Leap years. */ 108 /* Leap years. */
114 { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 } 109 { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
115 }; 110 };
116 111
117 static struct tm *ranged_convert __P ((struct tm *(*) __P ((const time_t *,
118 struct tm *)),
119 time_t *, struct tm *));
120 static time_t ydhms_tm_diff __P ((int, int, int, int, int, const struct tm *));
121 time_t __mktime_internal __P ((struct tm *,
122 struct tm *(*) (const time_t *, struct tm *),
123 time_t *));
124
125 112
126 #ifdef _LIBC 113 #ifdef _LIBC
127 # define localtime_r __localtime_r 114 # define my_mktime_localtime_r __localtime_r
128 #else 115 #else
129 # if ! HAVE_LOCALTIME_R && ! defined localtime_r 116 /* If we're a mktime substitute in a GNU program, then prefer
130 /* Approximate localtime_r as best we can in its absence. */ 117 localtime to localtime_r, since many localtime_r implementations
131 # define localtime_r my_mktime_localtime_r 118 are buggy. */
132 static struct tm *localtime_r __P ((const time_t *, struct tm *));
133 static struct tm * 119 static struct tm *
134 localtime_r (t, tp) 120 my_mktime_localtime_r (const time_t *t, struct tm *tp)
135 const time_t *t;
136 struct tm *tp;
137 { 121 {
138 struct tm *l = localtime (t); 122 struct tm *l = localtime (t);
139 if (! l) 123 if (! l)
140 return 0; 124 return 0;
141 *tp = *l; 125 *tp = *l;
142 return tp; 126 return tp;
143 } 127 }
144 # endif /* ! HAVE_LOCALTIME_R && ! defined (localtime_r) */
145 #endif /* ! _LIBC */ 128 #endif /* ! _LIBC */
146 129
147 130
148 /* Yield the difference between (YEAR-YDAY HOUR:MIN:SEC) and (*TP), 131 /* Yield the difference between (YEAR-YDAY HOUR:MIN:SEC) and (*TP),
149 measured in seconds, ignoring leap seconds. 132 measured in seconds, ignoring leap seconds.
150 YEAR uses the same numbering as TM->tm_year. 133 YEAR uses the same numbering as TM->tm_year.
151 All values are in range, except possibly YEAR. 134 All values are in range, except possibly YEAR.
152 If TP is null, return a nonzero value. 135 If TP is null, return a nonzero value.
153 If overflow occurs, yield the low order bits of the correct answer. */ 136 If overflow occurs, yield the low order bits of the correct answer. */
154 static time_t 137 static time_t
155 ydhms_tm_diff (year, yday, hour, min, sec, tp) 138 ydhms_tm_diff (int year, int yday, int hour, int min, int sec,
156 int year, yday, hour, min, sec; 139 const struct tm *tp)
157 const struct tm *tp;
158 { 140 {
159 if (!tp) 141 if (!tp)
160 return 1; 142 return 1;
161 else 143 else
162 { 144 {
179 + (min - tp->tm_min)) 161 + (min - tp->tm_min))
180 + (sec - tp->tm_sec)); 162 + (sec - tp->tm_sec));
181 } 163 }
182 } 164 }
183 165
184
185 static time_t localtime_offset;
186
187 /* Convert *TP to a time_t value. */
188 time_t
189 mktime (tp)
190 struct tm *tp;
191 {
192 #ifdef _LIBC
193 /* POSIX.1 8.1.1 requires that whenever mktime() is called, the
194 time zone names contained in the external variable `tzname' shall
195 be set as if the tzset() function had been called. */
196 __tzset ();
197 #endif
198
199 return __mktime_internal (tp, localtime_r, &localtime_offset);
200 }
201
202 /* Use CONVERT to convert *T to a broken down time in *TP. 166 /* Use CONVERT to convert *T to a broken down time in *TP.
203 If *T is out of range for conversion, adjust it so that 167 If *T is out of range for conversion, adjust it so that
204 it is the nearest in-range value and then convert that. */ 168 it is the nearest in-range value and then convert that. */
205 static struct tm * 169 static struct tm *
206 ranged_convert (convert, t, tp) 170 ranged_convert (struct tm *(*convert) (const time_t *, struct tm *),
207 struct tm *(*convert) __P ((const time_t *, struct tm *)); 171 time_t *t, struct tm *tp)
208 time_t *t;
209 struct tm *tp;
210 { 172 {
211 struct tm *r; 173 struct tm *r;
212 174
213 if (! (r = (*convert) (t, tp)) && *t) 175 if (! (r = (*convert) (t, tp)) && *t)
214 { 176 {
251 the monotonic and mostly-unit-linear conversion function CONVERT. 213 the monotonic and mostly-unit-linear conversion function CONVERT.
252 Use *OFFSET to keep track of a guess at the offset of the result, 214 Use *OFFSET to keep track of a guess at the offset of the result,
253 compared to what the result would be for UTC without leap seconds. 215 compared to what the result would be for UTC without leap seconds.
254 If *OFFSET's guess is correct, only one CONVERT call is needed. */ 216 If *OFFSET's guess is correct, only one CONVERT call is needed. */
255 time_t 217 time_t
256 __mktime_internal (tp, convert, offset) 218 __mktime_internal (struct tm *tp,
257 struct tm *tp; 219 struct tm *(*convert) (const time_t *, struct tm *),
258 struct tm *(*convert) __P ((const time_t *, struct tm *)); 220 time_t *offset)
259 time_t *offset; 221 {
260 { 222 time_t t, dt, t0, t1, t2;
261 time_t t, dt, t0;
262 struct tm tm; 223 struct tm tm;
263 224
264 /* The maximum number of probes (calls to CONVERT) should be enough 225 /* The maximum number of probes (calls to CONVERT) should be enough
265 to handle any combinations of time zone rule changes, solar time, 226 to handle any combinations of time zone rule changes, solar time,
266 and leap seconds. POSIX.1 prohibits leap seconds, but some hosts 227 leap seconds, and oscillations around a spring-forward gap.
267 have them anyway. */ 228 POSIX.1 prohibits leap seconds, but some hosts have them anyway. */
268 int remaining_probes = 4; 229 int remaining_probes = 6;
269 230
270 /* Time requested. Copy it in case CONVERT modifies *TP; this can 231 /* Time requested. Copy it in case CONVERT modifies *TP; this can
271 occur if TP is localtime's returned value and CONVERT is localtime. */ 232 occur if TP is localtime's returned value and CONVERT is localtime. */
272 int sec = tp->tm_sec; 233 int sec = tp->tm_sec;
273 int min = tp->tm_min; 234 int min = tp->tm_min;
309 270
310 tm.tm_year = EPOCH_YEAR - TM_YEAR_BASE; 271 tm.tm_year = EPOCH_YEAR - TM_YEAR_BASE;
311 tm.tm_yday = tm.tm_hour = tm.tm_min = tm.tm_sec = 0; 272 tm.tm_yday = tm.tm_hour = tm.tm_min = tm.tm_sec = 0;
312 t0 = ydhms_tm_diff (year, yday, hour, min, sec, &tm); 273 t0 = ydhms_tm_diff (year, yday, hour, min, sec, &tm);
313 274
314 for (t = t0 + *offset; 275 for (t = t1 = t2 = t0 + *offset;
315 (dt = ydhms_tm_diff (year, yday, hour, min, sec, 276 (dt = ydhms_tm_diff (year, yday, hour, min, sec,
316 ranged_convert (convert, &t, &tm))); 277 ranged_convert (convert, &t, &tm)));
317 t += dt) 278 t1 = t2, t2 = t, t += dt)
318 if (--remaining_probes == 0) 279 if (t == t1 && t != t2
280 && (isdst < 0 || tm.tm_isdst < 0
281 || (isdst != 0) != (tm.tm_isdst != 0)))
282 /* We can't possibly find a match, as we are oscillating
283 between two values. The requested time probably falls
284 within a spring-forward gap of size DT. Follow the common
285 practice in this case, which is to return a time that is DT
286 away from the requested time, preferring a time whose
287 tm_isdst differs from the requested value. In practice,
288 this is more useful than returning -1. */
289 break;
290 else if (--remaining_probes == 0)
319 return -1; 291 return -1;
320 292
321 /* Check whether tm.tm_isdst has the requested value, if any. */ 293 /* If we have a match, check whether tm.tm_isdst has the requested
322 if (0 <= isdst && 0 <= tm.tm_isdst) 294 value, if any. */
323 { 295 if (dt == 0 && isdst != tm.tm_isdst && 0 <= isdst && 0 <= tm.tm_isdst)
324 int dst_diff = (isdst != 0) - (tm.tm_isdst != 0); 296 {
325 if (dst_diff) 297 /* tm.tm_isdst has the wrong value. Look for a neighboring
298 time with the right value, and use its UTC offset.
299 Heuristic: probe the previous three calendar quarters (approximately),
300 looking for the desired isdst. This isn't perfect,
301 but it's good enough in practice. */
302 int quarter = 7889238; /* seconds per average 1/4 Gregorian year */
303 int i;
304
305 /* If we're too close to the time_t limit, look in future quarters. */
306 if (t < TIME_T_MIN + 3 * quarter)
307 quarter = -quarter;
308
309 for (i = 1; i <= 3; i++)
326 { 310 {
327 /* Move two hours in the direction indicated by the disagreement, 311 time_t ot = t - i * quarter;
328 probe some more, and switch to a new time if found. 312 struct tm otm;
329 The largest known fallback due to daylight savings is two hours: 313 ranged_convert (convert, &ot, &otm);
330 once, in Newfoundland, 1988-10-30 02:00 -> 00:00. */ 314 if (otm.tm_isdst == isdst)
331 time_t ot = t - 2 * 60 * 60 * dst_diff;
332 while (--remaining_probes != 0)
333 { 315 {
334 struct tm otm; 316 /* We found the desired tm_isdst.
335 if (! (dt = ydhms_tm_diff (year, yday, hour, min, sec, 317 Extrapolate back to the desired time. */
336 ranged_convert (convert, &ot, &otm)))) 318 t = ot + ydhms_tm_diff (year, yday, hour, min, sec, &otm);
337 { 319 ranged_convert (convert, &t, &tm);
338 t = ot; 320 break;
339 tm = otm;
340 break;
341 }
342 if ((ot += dt) == t)
343 break; /* Avoid a redundant probe. */
344 } 321 }
345 } 322 }
346 } 323 }
347 324
348 *offset = t - t0; 325 *offset = t - t0;
382 return -1; 359 return -1;
383 } 360 }
384 361
385 *tp = tm; 362 *tp = tm;
386 return t; 363 return t;
364 }
365
366
367 static time_t localtime_offset;
368
369 /* Convert *TP to a time_t value. */
370 time_t
371 mktime (tp)
372 struct tm *tp;
373 {
374 #ifdef _LIBC
375 /* POSIX.1 8.1.1 requires that whenever mktime() is called, the
376 time zone names contained in the external variable `tzname' shall
377 be set as if the tzset() function had been called. */
378 __tzset ();
379 #endif
380
381 return __mktime_internal (tp, my_mktime_localtime_r, &localtime_offset);
387 } 382 }
388 383
389 #ifdef weak_alias 384 #ifdef weak_alias
390 weak_alias (mktime, timelocal) 385 weak_alias (mktime, timelocal)
391 #endif 386 #endif
528 523
529 #endif /* DEBUG */ 524 #endif /* DEBUG */
530 525
531 /* 526 /*
532 Local Variables: 527 Local Variables:
533 compile-command: "gcc -DDEBUG -D__EXTENSIONS__ -DHAVE_LIMITS_H -DHAVE_LOCALTIME_R -DSTDC_HEADERS -Wall -W -O -g mktime.c -o mktime" 528 compile-command: "gcc -DDEBUG -DHAVE_LIMITS_H -DSTDC_HEADERS -Wall -W -O -g mktime.c -o mktime"
534 End: 529 End:
535 */ 530 */