38094b039d0f337a1f7b53b82c81df7d8148da67
[pspp] / lib / gettimeofday.c
1 /* Provide gettimeofday
2    1. for systems that don't have it,
3    2. for some systems where gettimeofday clobbers the static buffer that
4       localtime uses for it's return value.  The gettimeofday function from
5       Mac OS X 10.0.4, i.e. Darwin 1.3.7 has this problem.
6       The tzset replacement is necessary for at least Solaris 2.5, 2.5.1, and
7       2.6.
8
9    Copyright (C) 2001, 2002, 2003, 2005, 2006, 2007 Free Software Foundation, Inc.
10
11    This program is free software; you can redistribute it and/or modify
12    it under the terms of the GNU General Public License as published by
13    the Free Software Foundation; either version 2, or (at your option)
14    any later version.
15
16    This program is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19    GNU General Public License for more details.
20
21    You should have received a copy of the GNU General Public License
22    along with this program; if not, write to the Free Software Foundation,
23    Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
24
25 /* written by Jim Meyering */
26
27 #include <config.h>
28
29 /* Specification.  */
30 #include "gettimeofday.h"
31
32 #include <sys/types.h>
33 #include <stdlib.h>
34
35 #if HAVE_SYS_TIMEB_H
36 # include <sys/timeb.h>
37 #endif
38
39 #if GETTIMEOFDAY_CLOBBERS_LOCALTIME
40
41 static struct tm *localtime_buffer_addr;
42
43 /* This is a wrapper for localtime.  It is used only on systems for which
44    gettimeofday clobbers the static buffer used for localtime's result.
45
46    On the first call, record the address of the static buffer that
47    localtime uses for its result.  */
48
49 struct tm *
50 localtime (const time_t *timep)
51 #undef localtime
52 {
53   extern struct tm *localtime (const time_t *);
54   struct tm *tm = localtime (timep);
55
56   if (! localtime_buffer_addr)
57     localtime_buffer_addr = tm;
58
59   return tm;
60 }
61
62 /* Same as above, since gmtime and localtime use the same buffer.  */
63 struct tm *
64 gmtime (const time_t *timep)
65 #undef gmtime
66 {
67   extern struct tm *gmtime (const time_t *);
68   struct tm *tm = gmtime (timep);
69
70   if (! localtime_buffer_addr)
71     localtime_buffer_addr = tm;
72
73   return tm;
74 }
75
76 /* This is a wrapper for tzset. It is used only on systems for which
77    tzset may clobber the static buffer used for localtime's result.
78    Save and restore the contents of the buffer used for localtime's
79    result around the call to tzset.  */
80 void
81 tzset (void)
82 #undef tzset
83 {
84   extern struct tm *localtime (const time_t *);
85   extern void tzset (void);
86   struct tm save;
87
88   if (! localtime_buffer_addr)
89     {
90       time_t t = 0;
91       localtime_buffer_addr = localtime (&t);
92     }
93
94   save = *localtime_buffer_addr;
95   tzset ();
96   *localtime_buffer_addr = save;
97 }
98
99 #endif
100
101 /* This is a wrapper for gettimeofday.
102    It is used only on systems that lack this function, or for whose
103    implementation of this function causes problems. */
104
105 int
106 gettimeofday (struct timeval *restrict tv, void *restrict tz)
107 #undef gettimeofday
108 {
109 #if HAVE_GETTIMEOFDAY
110   extern int gettimeofday (/* unspecified arguments */);
111 # if GETTIMEOFDAY_CLOBBERS_LOCALTIME
112   extern struct tm *localtime (const time_t *);
113
114   /* Save and restore the contents of the buffer used for localtime's result
115      around the call to gettimeofday. */
116   struct tm save;
117   int result;
118
119   if (! localtime_buffer_addr)
120     {
121       time_t t = 0;
122       localtime_buffer_addr = localtime (&t);
123     }
124
125   save = *localtime_buffer_addr;
126   result = gettimeofday (tv, tz);
127   *localtime_buffer_addr = save;
128
129   return result;
130
131 # else
132
133   return gettimeofday (tv, tz);
134
135 # endif
136 #else
137
138   /* The clock does not have microsecond resolution, so get the maximum
139      possible value for the current time that is consistent with the
140      reported clock.  That way, files are not considered to be in the
141      future merely because their time stamps have higher resolution
142      than the clock resolution.  */
143
144 # if HAVE__FTIME
145
146   struct _timeb timebuf;
147
148   _ftime (&timebuf);
149   tv->tv_sec = timebuf.time;
150   tv->tv_usec = timebuf.millitm * 1000 + 999;
151
152   return 0;
153
154 # else
155
156   time_t t = time (NULL);
157
158   if (t == (time_t) -1)
159     return -1;
160   tv->tv_sec = t;
161   tv->tv_usec = 999999;
162
163   return 0;
164
165 # endif
166 #endif
167 }