]> git.ipfire.org Git - thirdparty/glibc.git/blame - time/zdump.c
Wed Jun 5 15:57:28 1996 Roland McGrath <roland@delasyd.gnu.ai.mit.edu>
[thirdparty/glibc.git] / time / zdump.c
CommitLineData
28f540f4
RM
1#ifndef lint
2#ifndef NOID
92777700 3static char elsieid[] = "@(#)zdump.c 7.23";
28f540f4
RM
4#endif /* !defined NOID */
5#endif /* !defined lint */
6
7/*
8** This code has been made independent of the rest of the time
9** conversion package to increase confidence in the verification it provides.
10** You can use this code to help in verifying other implementations.
11*/
12
6c2f0507 13#include "stdio.h" /* for stdout, stderr, perror */
28f540f4
RM
14#include "string.h" /* for strcpy */
15#include "sys/types.h" /* for time_t */
16#include "time.h" /* for struct tm */
6c2f0507 17#include "stdlib.h" /* for exit, malloc, atoi */
28f540f4
RM
18
19#ifndef MAX_STRING_LENGTH
20#define MAX_STRING_LENGTH 1024
21#endif /* !defined MAX_STRING_LENGTH */
22
23#ifndef TRUE
24#define TRUE 1
25#endif /* !defined TRUE */
26
27#ifndef FALSE
28#define FALSE 0
29#endif /* !defined FALSE */
30
31#ifndef EXIT_SUCCESS
32#define EXIT_SUCCESS 0
33#endif /* !defined EXIT_SUCCESS */
34
35#ifndef EXIT_FAILURE
36#define EXIT_FAILURE 1
37#endif /* !defined EXIT_FAILURE */
38
39#ifndef SECSPERMIN
40#define SECSPERMIN 60
41#endif /* !defined SECSPERMIN */
42
43#ifndef MINSPERHOUR
44#define MINSPERHOUR 60
45#endif /* !defined MINSPERHOUR */
46
47#ifndef SECSPERHOUR
48#define SECSPERHOUR (SECSPERMIN * MINSPERHOUR)
49#endif /* !defined SECSPERHOUR */
50
51#ifndef HOURSPERDAY
52#define HOURSPERDAY 24
53#endif /* !defined HOURSPERDAY */
54
55#ifndef EPOCH_YEAR
56#define EPOCH_YEAR 1970
57#endif /* !defined EPOCH_YEAR */
58
59#ifndef TM_YEAR_BASE
60#define TM_YEAR_BASE 1900
61#endif /* !defined TM_YEAR_BASE */
62
63#ifndef DAYSPERNYEAR
64#define DAYSPERNYEAR 365
65#endif /* !defined DAYSPERNYEAR */
66
67#ifndef isleap
68#define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0)
69#endif /* !defined isleap */
70
92777700
RM
71#if HAVE_GETTEXT - 0
72#include "locale.h" /* for setlocale */
73#include "libintl.h"
74#endif /* HAVE_GETTEXT - 0 */
75
28f540f4
RM
76#ifndef GNUC_or_lint
77#ifdef lint
78#define GNUC_or_lint
79#endif /* defined lint */
6c2f0507 80#ifndef lint
28f540f4
RM
81#ifdef __GNUC__
82#define GNUC_or_lint
83#endif /* defined __GNUC__ */
6c2f0507 84#endif /* !defined lint */
28f540f4
RM
85#endif /* !defined GNUC_or_lint */
86
87#ifndef INITIALIZE
88#ifdef GNUC_or_lint
89#define INITIALIZE(x) ((x) = 0)
90#endif /* defined GNUC_or_lint */
91#ifndef GNUC_or_lint
92#define INITIALIZE(x)
93#endif /* !defined GNUC_or_lint */
94#endif /* !defined INITIALIZE */
95
a182affd
RM
96/*
97** For the benefit of GNU folk...
92777700
RM
98** `_(MSGID)' uses the current locale's message library string for MSGID.
99** The default is to use gettext if available, and use MSGID otherwise.
a182affd
RM
100*/
101
102#ifndef _
92777700
RM
103#if HAVE_GETTEXT - 0
104#define _(msgid) gettext(msgid)
105#else /* !(HAVE_GETTEXT - 0) */
106#define _(msgid) msgid
107#endif /* !(HAVE_GETTEXT - 0) */
a182affd
RM
108#endif /* !defined _ */
109
92777700
RM
110#ifndef TZ_DOMAIN
111#define TZ_DOMAIN "tz"
112#endif /* !defined TZ_DOMAIN */
113
28f540f4
RM
114extern char ** environ;
115extern int getopt();
116extern char * optarg;
117extern int optind;
118extern time_t time();
119extern char * tzname[2];
120
28f540f4
RM
121static char * abbr();
122static long delta();
123static time_t hunt();
124static int longest;
125static char * progname;
126static void show();
127
128int
129main(argc, argv)
130int argc;
131char * argv[];
132{
6c2f0507
RM
133 register int i;
134 register int c;
28f540f4
RM
135 register int vflag;
136 register char * cutoff;
137 register int cutyear;
138 register long cuttime;
139 char ** fakeenv;
140 time_t now;
6c2f0507
RM
141 time_t t;
142 time_t newt;
28f540f4 143 time_t hibit;
6c2f0507
RM
144 struct tm tm;
145 struct tm newtm;
28f540f4
RM
146
147 INITIALIZE(cuttime);
92777700
RM
148#if HAVE_GETTEXT - 0
149 (void) setlocale(LC_MESSAGES, "");
150#ifdef TZ_DOMAINDIR
151 (void) bindtextdomain(TZ_DOMAIN, TZ_DOMAINDIR);
152#endif /* defined(TEXTDOMAINDIR) */
153 (void) textdomain(TZ_DOMAIN);
154#endif /* HAVE_GETTEXT - 0 */
28f540f4
RM
155 progname = argv[0];
156 vflag = 0;
157 cutoff = NULL;
158 while ((c = getopt(argc, argv, "c:v")) == 'c' || c == 'v')
159 if (c == 'v')
160 vflag = 1;
161 else cutoff = optarg;
162 if (c != EOF ||
163 (optind == argc - 1 && strcmp(argv[optind], "=") == 0)) {
164 (void) fprintf(stderr,
cbd3dceb 165_("%s: usage is %s [ -v ] [ -c cutoff ] zonename ...\n"),
28f540f4
RM
166 argv[0], argv[0]);
167 (void) exit(EXIT_FAILURE);
168 }
169 if (cutoff != NULL) {
170 int y;
171
172 cutyear = atoi(cutoff);
173 cuttime = 0;
174 for (y = EPOCH_YEAR; y < cutyear; ++y)
175 cuttime += DAYSPERNYEAR + isleap(y);
176 cuttime *= SECSPERHOUR * HOURSPERDAY;
177 }
178 (void) time(&now);
179 longest = 0;
180 for (i = optind; i < argc; ++i)
181 if (strlen(argv[i]) > longest)
182 longest = strlen(argv[i]);
183 for (hibit = 1; (hibit << 1) != 0; hibit <<= 1)
184 continue;
185 {
6c2f0507
RM
186 register int from;
187 register int to;
28f540f4
RM
188
189 for (i = 0; environ[i] != NULL; ++i)
190 continue;
6c2f0507
RM
191 fakeenv = (char **) malloc((size_t) ((i + 2) *
192 sizeof *fakeenv));
28f540f4 193 if (fakeenv == NULL ||
6c2f0507
RM
194 (fakeenv[0] = (char *) malloc((size_t) (longest +
195 4))) == NULL) {
196 (void) perror(progname);
197 (void) exit(EXIT_FAILURE);
28f540f4
RM
198 }
199 to = 0;
200 (void) strcpy(fakeenv[to++], "TZ=");
201 for (from = 0; environ[from] != NULL; ++from)
202 if (strncmp(environ[from], "TZ=", 3) != 0)
203 fakeenv[to++] = environ[from];
204 fakeenv[to] = NULL;
205 environ = fakeenv;
206 }
207 for (i = optind; i < argc; ++i) {
208 static char buf[MAX_STRING_LENGTH];
209
210 (void) strcpy(&fakeenv[0][3], argv[i]);
211 show(argv[i], now, FALSE);
212 if (!vflag)
213 continue;
214 /*
215 ** Get lowest value of t.
216 */
217 t = hibit;
218 if (t > 0) /* time_t is unsigned */
219 t = 0;
220 show(argv[i], t, TRUE);
221 t += SECSPERHOUR * HOURSPERDAY;
222 show(argv[i], t, TRUE);
223 tm = *localtime(&t);
224 (void) strncpy(buf, abbr(&tm), (sizeof buf) - 1);
225 for ( ; ; ) {
226 if (cutoff != NULL && t >= cuttime)
227 break;
228 newt = t + SECSPERHOUR * 12;
229 if (cutoff != NULL && newt >= cuttime)
230 break;
231 if (newt <= t)
232 break;
233 newtm = *localtime(&newt);
234 if (delta(&newtm, &tm) != (newt - t) ||
235 newtm.tm_isdst != tm.tm_isdst ||
236 strcmp(abbr(&newtm), buf) != 0) {
237 newt = hunt(argv[i], t, newt);
238 newtm = *localtime(&newt);
239 (void) strncpy(buf, abbr(&newtm),
240 (sizeof buf) - 1);
241 }
242 t = newt;
243 tm = newtm;
244 }
245 /*
246 ** Get highest value of t.
247 */
248 t = ~((time_t) 0);
249 if (t < 0) /* time_t is signed */
250 t &= ~hibit;
251 t -= SECSPERHOUR * HOURSPERDAY;
252 show(argv[i], t, TRUE);
253 t += SECSPERHOUR * HOURSPERDAY;
254 show(argv[i], t, TRUE);
255 }
256 if (fflush(stdout) || ferror(stdout)) {
cbd3dceb 257 (void) fprintf(stderr, _("%s: Error writing standard output "),
28f540f4 258 argv[0]);
cbd3dceb 259 (void) perror(_("standard output"));
28f540f4
RM
260 (void) exit(EXIT_FAILURE);
261 }
262 exit(EXIT_SUCCESS);
263
264 /* gcc -Wall pacifier */
265 for ( ; ; )
266 continue;
267}
268
269static time_t
270hunt(name, lot, hit)
271char * name;
272time_t lot;
273time_t hit;
274{
275 time_t t;
276 struct tm lotm;
277 struct tm tm;
278 static char loab[MAX_STRING_LENGTH];
279
280 lotm = *localtime(&lot);
281 (void) strncpy(loab, abbr(&lotm), (sizeof loab) - 1);
282 while ((hit - lot) >= 2) {
283 t = lot / 2 + hit / 2;
284 if (t <= lot)
285 ++t;
286 else if (t >= hit)
287 --t;
288 tm = *localtime(&t);
289 if (delta(&tm, &lotm) == (t - lot) &&
290 tm.tm_isdst == lotm.tm_isdst &&
291 strcmp(abbr(&tm), loab) == 0) {
292 lot = t;
293 lotm = tm;
294 } else hit = t;
295 }
296 show(name, lot, TRUE);
297 show(name, hit, TRUE);
298 return hit;
299}
300
301/*
302** Thanks to Paul Eggert (eggert@twinsun.com) for logic used in delta.
303*/
304
305static long
306delta(newp, oldp)
307struct tm * newp;
308struct tm * oldp;
309{
310 long result;
311 int tmy;
312
313 if (newp->tm_year < oldp->tm_year)
314 return -delta(oldp, newp);
315 result = 0;
316 for (tmy = oldp->tm_year; tmy < newp->tm_year; ++tmy)
317 result += DAYSPERNYEAR + isleap(tmy + TM_YEAR_BASE);
318 result += newp->tm_yday - oldp->tm_yday;
319 result *= HOURSPERDAY;
320 result += newp->tm_hour - oldp->tm_hour;
321 result *= MINSPERHOUR;
322 result += newp->tm_min - oldp->tm_min;
323 result *= SECSPERMIN;
324 result += newp->tm_sec - oldp->tm_sec;
325 return result;
326}
327
328extern struct tm * localtime();
329
330static void
331show(zone, t, v)
332char * zone;
333time_t t;
334int v;
335{
336 struct tm * tmp;
337
338 (void) printf("%-*s ", longest, zone);
339 if (v)
340 (void) printf("%.24s GMT = ", asctime(gmtime(&t)));
341 tmp = localtime(&t);
342 (void) printf("%.24s", asctime(tmp));
343 if (*abbr(tmp) != '\0')
344 (void) printf(" %s", abbr(tmp));
345 if (v) {
346 (void) printf(" isdst=%d", tmp->tm_isdst);
347#ifdef TM_GMTOFF
348 (void) printf(" gmtoff=%ld", tmp->TM_GMTOFF);
349#endif /* defined TM_GMTOFF */
350 }
351 (void) printf("\n");
352}
353
354static char *
355abbr(tmp)
356struct tm * tmp;
357{
358 register char * result;
359 static char nada;
360
361 if (tmp->tm_isdst != 0 && tmp->tm_isdst != 1)
362 return &nada;
363 result = tzname[tmp->tm_isdst];
364 return (result == NULL) ? &nada : result;
365}