Remove K&R cruft.
[gnulib.git] / lib / mktime.c
1 /* Convert a `struct tm' to a time_t value.
2    Copyright (C) 1993-1999, 2002, 2003 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4    Contributed by Paul Eggert (eggert@twinsun.com).
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2, or (at your option)
9    any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License along
17    with this program; if not, write to the Free Software Foundation,
18    Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
19
20 /* Define this to have a standalone program to test this implementation of
21    mktime.  */
22 /* #define DEBUG 1 */
23
24 #ifdef HAVE_CONFIG_H
25 # include <config.h>
26 #endif
27
28 /* Assume that leap seconds are possible, unless told otherwise.
29    If the host has a `zic' command with a `-L leapsecondfilename' option,
30    then it supports leap seconds; otherwise it probably doesn't.  */
31 #ifndef LEAP_SECONDS_POSSIBLE
32 # define LEAP_SECONDS_POSSIBLE 1
33 #endif
34
35 #include <sys/types.h>          /* Some systems define `time_t' here.  */
36 #include <time.h>
37
38 #include <limits.h>
39
40 #if DEBUG
41 # include <stdio.h>
42 # include <stdlib.h>
43 # include <string.h>
44 /* Make it work even if the system's libc has its own mktime routine.  */
45 # define mktime my_mktime
46 #endif /* DEBUG */
47
48 /* The extra casts work around common compiler bugs.  */
49 #define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
50 /* The outer cast is needed to work around a bug in Cray C 5.0.3.0.
51    It is necessary at least when t == time_t.  */
52 #define TYPE_MINIMUM(t) ((t) (TYPE_SIGNED (t) \
53                               ? ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1) : (t) 0))
54 #define TYPE_MAXIMUM(t) ((t) (~ (t) 0 - TYPE_MINIMUM (t)))
55
56 #ifndef TIME_T_MIN
57 # define TIME_T_MIN TYPE_MINIMUM (time_t)
58 #endif
59 #ifndef TIME_T_MAX
60 # define TIME_T_MAX TYPE_MAXIMUM (time_t)
61 #endif
62 #define TIME_T_MIDPOINT (((TIME_T_MIN + TIME_T_MAX) >> 1) + 1)
63
64 /* Verify a requirement at compile-time (unlike assert, which is runtime).  */
65 #define verify(name, assertion) struct name { char a[(assertion) ? 1 : -1]; }
66
67 verify (time_t_is_integer, (time_t) 0.5 == 0);
68 verify (twos_complement_arithmetic, -1 == ~1 + 1);
69 verify (right_shift_propagates_sign, -1 >> 1 == -1);
70 /* The code also assumes that signed integer overflow silently wraps
71    around, but this assumption can't be stated without causing a
72    diagnostic on some hosts.  */
73
74 #define EPOCH_YEAR 1970
75 #define TM_YEAR_BASE 1900
76 verify (base_year_is_a_multiple_of_100, TM_YEAR_BASE % 100 == 0);
77
78 /* Return 1 if YEAR + TM_YEAR_BASE is a leap year.  */
79 static inline int
80 leapyear (int year)
81 {
82   /* Don't add YEAR to TM_YEAR_BASE, as that might overflow.
83      Also, work even if YEAR is negative.  */
84   return
85     ((year & 3) == 0
86      && (year % 100 != 0
87          || ((year / 100) & 3) == (- (TM_YEAR_BASE / 100) & 3)));
88 }
89
90 /* How many days come before each month (0-12).  */
91 #ifndef _LIBC
92 static
93 #endif
94 const unsigned short int __mon_yday[2][13] =
95   {
96     /* Normal years.  */
97     { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
98     /* Leap years.  */
99     { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
100   };
101
102
103 #ifndef _LIBC
104 /* Portable standalone applications should supply a "time_r.h" that
105    declares a POSIX-compliant localtime_r, for the benefit of older
106    implementations that lack localtime_r or have a nonstandard one.
107    See the gnulib time_r module for one way to implement this.  */
108 # include "time_r.h"
109 # undef __localtime_r
110 # define __localtime_r localtime_r
111 #endif
112
113 /* Return an integer value measuring (YEAR1-YDAY1 HOUR1:MIN1:SEC1) -
114    (YEAR0-YDAY0 HOUR0:MIN0:SEC0) in seconds, assuming that the clocks
115    were not adjusted between the time stamps.
116
117    The YEAR values uses the same numbering as TP->tm_year.  Values
118    need not be in the usual range.  However, YEAR1 must not be less
119    than 2 * INT_MIN or greater than 2 * INT_MAX.
120
121    The result may overflow.  It is the caller's responsibility to
122    detect overflow.  */
123
124 static inline time_t
125 ydhms_diff (long int year1, long int yday1, int hour1, int min1, int sec1,
126             int year0, int yday0, int hour0, int min0, int sec0)
127 {
128   verify (C99_integer_division, -1 / 2 == 0);
129   verify (long_int_year_and_yday_are_wide_enough,
130           INT_MAX <= LONG_MAX / 2 || TIME_T_MAX <= UINT_MAX);
131
132   /* Compute intervening leap days correctly even if year is negative.
133      Take care to avoid integer overflow here.  */
134   int a4 = (year1 >> 2) + (TM_YEAR_BASE >> 2) - ! (year1 & 3);
135   int b4 = (year0 >> 2) + (TM_YEAR_BASE >> 2) - ! (year0 & 3);
136   int a100 = a4 / 25 - (a4 % 25 < 0);
137   int b100 = b4 / 25 - (b4 % 25 < 0);
138   int a400 = a100 >> 2;
139   int b400 = b100 >> 2;
140   int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
141
142   /* Compute the desired time in time_t precision.  Overflow might
143      occur here.  */
144   time_t tyear1 = year1;
145   time_t years = tyear1 - year0;
146   time_t days = 365 * years + yday1 - yday0 + intervening_leap_days;
147   time_t hours = 24 * days + hour1 - hour0;
148   time_t minutes = 60 * hours + min1 - min0;
149   time_t seconds = 60 * minutes + sec1 - sec0;
150   return seconds;
151 }
152
153
154 /* Return a time_t value corresponding to (YEAR-YDAY HOUR:MIN:SEC),
155    assuming that *T corresponds to *TP and that no clock adjustments
156    occurred between *TP and the desired time.
157    If TP is null, return a value not equal to *T; this avoids false matches.
158    If overflow occurs, yield the minimal or maximal value, except do not
159    yield a value equal to *T.  */
160 static time_t
161 guess_time_tm (long int year, long int yday, int hour, int min, int sec,
162                const time_t *t, const struct tm *tp)
163 {
164   if (tp)
165     {
166       time_t d = ydhms_diff (year, yday, hour, min, sec,
167                              tp->tm_year, tp->tm_yday,
168                              tp->tm_hour, tp->tm_min, tp->tm_sec);
169       time_t t1 = *t + d;
170       if ((t1 < *t) == (TYPE_SIGNED (time_t) ? d < 0 : TIME_T_MAX / 2 < d))
171         return t1;
172     }
173
174   /* Overflow occurred one way or another.  Return the nearest result
175      that is actually in range, except don't report a zero difference
176      if the actual difference is nonzero, as that would cause a false
177      match.  */
178   return (*t < TIME_T_MIDPOINT
179           ? TIME_T_MIN + (*t == TIME_T_MIN)
180           : TIME_T_MAX - (*t == TIME_T_MAX));
181 }
182
183 /* Use CONVERT to convert *T to a broken down time in *TP.
184    If *T is out of range for conversion, adjust it so that
185    it is the nearest in-range value and then convert that.  */
186 static struct tm *
187 ranged_convert (struct tm *(*convert) (const time_t *, struct tm *),
188                 time_t *t, struct tm *tp)
189 {
190   struct tm *r;
191
192   if (! (r = (*convert) (t, tp)) && *t)
193     {
194       time_t bad = *t;
195       time_t ok = 0;
196       struct tm tm;
197
198       /* BAD is a known unconvertible time_t, and OK is a known good one.
199          Use binary search to narrow the range between BAD and OK until
200          they differ by 1.  */
201       while (bad != ok + (bad < 0 ? -1 : 1))
202         {
203           time_t mid = *t = (bad < 0
204                              ? bad + ((ok - bad) >> 1)
205                              : ok + ((bad - ok) >> 1));
206           if ((r = (*convert) (t, tp)))
207             {
208               tm = *r;
209               ok = mid;
210             }
211           else
212             bad = mid;
213         }
214
215       if (!r && ok)
216         {
217           /* The last conversion attempt failed;
218              revert to the most recent successful attempt.  */
219           *t = ok;
220           *tp = tm;
221           r = tp;
222         }
223     }
224
225   return r;
226 }
227
228
229 /* Convert *TP to a time_t value, inverting
230    the monotonic and mostly-unit-linear conversion function CONVERT.
231    Use *OFFSET to keep track of a guess at the offset of the result,
232    compared to what the result would be for UTC without leap seconds.
233    If *OFFSET's guess is correct, only one CONVERT call is needed.  */
234 time_t
235 __mktime_internal (struct tm *tp,
236                    struct tm *(*convert) (const time_t *, struct tm *),
237                    time_t *offset)
238 {
239   time_t t, gt, t0, t1, t2;
240   struct tm tm;
241
242   /* The maximum number of probes (calls to CONVERT) should be enough
243      to handle any combinations of time zone rule changes, solar time,
244      leap seconds, and oscillations around a spring-forward gap.
245      POSIX.1 prohibits leap seconds, but some hosts have them anyway.  */
246   int remaining_probes = 6;
247
248   /* Time requested.  Copy it in case CONVERT modifies *TP; this can
249      occur if TP is localtime's returned value and CONVERT is localtime.  */
250   int sec = tp->tm_sec;
251   int min = tp->tm_min;
252   int hour = tp->tm_hour;
253   int mday = tp->tm_mday;
254   int mon = tp->tm_mon;
255   int year_requested = tp->tm_year;
256   int isdst = tp->tm_isdst;
257
258   /* 1 if the previous probe was DST.  */
259   int dst2;
260
261   /* Ensure that mon is in range, and set year accordingly.  */
262   int mon_remainder = mon % 12;
263   int negative_mon_remainder = mon_remainder < 0;
264   int mon_years = mon / 12 - negative_mon_remainder;
265   long int lyear_requested = year_requested;
266   long int year = lyear_requested + mon_years;
267
268   /* The other values need not be in range:
269      the remaining code handles minor overflows correctly,
270      assuming int and time_t arithmetic wraps around.
271      Major overflows are caught at the end.  */
272
273   /* Calculate day of year from year, month, and day of month.
274      The result need not be in range.  */
275   int mon_yday = ((__mon_yday[leapyear (year)]
276                    [mon_remainder + 12 * negative_mon_remainder])
277                   - 1);
278   long int lmday = mday;
279   long int yday = mon_yday + lmday;
280
281   time_t guessed_offset = *offset;
282
283   int sec_requested = sec;
284
285   if (LEAP_SECONDS_POSSIBLE)
286     {
287       /* Handle out-of-range seconds specially,
288          since ydhms_tm_diff assumes every minute has 60 seconds.  */
289       if (sec < 0)
290         sec = 0;
291       if (59 < sec)
292         sec = 59;
293     }
294
295   /* Invert CONVERT by probing.  First assume the same offset as last
296      time.  */
297
298   t0 = ydhms_diff (year, yday, hour, min, sec,
299                    EPOCH_YEAR - TM_YEAR_BASE, 0, 0, 0, - guessed_offset);
300
301   if (TIME_T_MAX / INT_MAX / 366 / 24 / 60 / 60 < 3)
302     {
303       /* time_t isn't large enough to rule out overflows, so check
304          for major overflows.  A gross check suffices, since if t0
305          has overflowed, it is off by a multiple of TIME_T_MAX -
306          TIME_T_MIN + 1.  So ignore any component of the difference
307          that is bounded by a small value.  */
308
309       /* Approximate log base 2 of the number of time units per
310          biennium.  A biennium is 2 years; use this unit instead of
311          years to avoid integer overflow.  For example, 2 average
312          Gregorian years are 2 * 365.2425 * 24 * 60 * 60 seconds,
313          which is 63113904 seconds, and rint (log2 (63113904)) is
314          26.  */
315       int ALOG2_SECONDS_PER_BIENNIUM = 26;
316       int ALOG2_MINUTES_PER_BIENNIUM = 20;
317       int ALOG2_HOURS_PER_BIENNIUM = 14;
318       int ALOG2_DAYS_PER_BIENNIUM = 10;
319       int LOG2_YEARS_PER_BIENNIUM = 1;
320
321       int approx_requested_biennia =
322         ((year_requested >> LOG2_YEARS_PER_BIENNIUM)
323          - ((EPOCH_YEAR - TM_YEAR_BASE) >> LOG2_YEARS_PER_BIENNIUM)
324          + (mday >> ALOG2_DAYS_PER_BIENNIUM)
325          + (hour >> ALOG2_HOURS_PER_BIENNIUM)
326          + (min >> ALOG2_MINUTES_PER_BIENNIUM)
327          + (LEAP_SECONDS_POSSIBLE ? 0 : sec >> ALOG2_SECONDS_PER_BIENNIUM));
328
329       int approx_biennia = t0 >> ALOG2_SECONDS_PER_BIENNIUM;
330       int diff = approx_biennia - approx_requested_biennia;
331       int abs_diff = diff < 0 ? - diff : diff;
332
333       /* IRIX 4.0.5 cc miscaculates TIME_T_MIN / 3: it erroneously
334          gives a positive value of 715827882.  Setting a variable
335          first then doing math on it seems to work.
336          (ghazi@caip.rutgers.edu) */
337       time_t time_t_max = TIME_T_MAX;
338       time_t time_t_min = TIME_T_MIN;
339       time_t overflow_threshold =
340         (time_t_max / 3 - time_t_min / 3) >> ALOG2_SECONDS_PER_BIENNIUM;
341
342       if (overflow_threshold < abs_diff)
343         {
344           /* Overflow occurred.  Try repairing it; this might work if
345              the time zone offset is enough to undo the overflow.  */
346           time_t repaired_t0 = -1 - t0;
347           approx_biennia = repaired_t0 >> ALOG2_SECONDS_PER_BIENNIUM;
348           diff = approx_biennia - approx_requested_biennia;
349           abs_diff = diff < 0 ? - diff : diff;
350           if (overflow_threshold < abs_diff)
351             return -1;
352           guessed_offset += repaired_t0 - t0;
353           t0 = repaired_t0;
354         }
355     }
356
357   /* Repeatedly use the error to improve the guess.  */
358
359   for (t = t1 = t2 = t0, dst2 = 0;
360        (gt = guess_time_tm (year, yday, hour, min, sec, &t,
361                             ranged_convert (convert, &t, &tm)),
362         t != gt);
363        t1 = t2, t2 = t, t = gt, dst2 = tm.tm_isdst != 0)
364     if (t == t1 && t != t2
365         && (tm.tm_isdst < 0
366             || (isdst < 0
367                 ? dst2 <= (tm.tm_isdst != 0)
368                 : (isdst != 0) != (tm.tm_isdst != 0))))
369       /* We can't possibly find a match, as we are oscillating
370          between two values.  The requested time probably falls
371          within a spring-forward gap of size GT - T.  Follow the common
372          practice in this case, which is to return a time that is GT - T
373          away from the requested time, preferring a time whose
374          tm_isdst differs from the requested value.  (If no tm_isdst
375          was requested and only one of the two values has a nonzero
376          tm_isdst, prefer that value.)  In practice, this is more
377          useful than returning -1.  */
378       goto offset_found;
379     else if (--remaining_probes == 0)
380       return -1;
381
382   /* We have a match.  Check whether tm.tm_isdst has the requested
383      value, if any.  */
384   if (isdst != tm.tm_isdst && 0 <= isdst && 0 <= tm.tm_isdst)
385     {
386       /* tm.tm_isdst has the wrong value.  Look for a neighboring
387          time with the right value, and use its UTC offset.
388
389          Heuristic: probe the adjacent timestamps in both directions,
390          looking for the desired isdst.  This should work for all real
391          time zone histories in the tz database.  */
392
393       /* Distance between probes when looking for a DST boundary.  In
394          tzdata2003a, the shortest period of DST is 601200 seconds
395          (e.g., America/Recife starting 2000-10-08 01:00), and the
396          shortest period of non-DST surrounded by DST is 694800
397          seconds (Africa/Tunis starting 1943-04-17 01:00).  Use the
398          minimum of these two values, so we don't miss these short
399          periods when probing.  */
400       int stride = 601200;
401
402       /* The longest period of DST in tzdata2003a is 536454000 seconds
403          (e.g., America/Jujuy starting 1946-10-01 01:00).  The longest
404          period of non-DST is much longer, but it makes no real sense
405          to search for more than a year of non-DST, so use the DST
406          max.  */
407       int duration_max = 536454000;
408
409       /* Search in both directions, so the maximum distance is half
410          the duration; add the stride to avoid off-by-1 problems.  */
411       int delta_bound = duration_max / 2 + stride;
412
413       int delta, direction;
414
415       for (delta = stride; delta < delta_bound; delta += stride)
416         for (direction = -1; direction <= 1; direction += 2)
417           {
418             time_t ot = t + delta * direction;
419             if ((ot < t) == (direction < 0))
420               {
421                 struct tm otm;
422                 ranged_convert (convert, &ot, &otm);
423                 if (otm.tm_isdst == isdst)
424                   {
425                     /* We found the desired tm_isdst.
426                        Extrapolate back to the desired time.  */
427                     t = guess_time_tm (year, yday, hour, min, sec, &ot, &otm);
428                     ranged_convert (convert, &t, &tm);
429                     goto offset_found;
430                   }
431               }
432           }
433     }
434
435  offset_found:
436   *offset = guessed_offset + t - t0;
437
438   if (LEAP_SECONDS_POSSIBLE && sec_requested != tm.tm_sec)
439     {
440       /* Adjust time to reflect the tm_sec requested, not the normalized value.
441          Also, repair any damage from a false match due to a leap second.  */
442       int sec_adjustment = (sec == 0 && tm.tm_sec == 60) - sec;
443       t1 = t + sec_requested;
444       t2 = t1 + sec_adjustment;
445       if (((t1 < t) != (sec_requested < 0))
446           | ((t2 < t1) != (sec_adjustment < 0))
447           | ! (*convert) (&t, &tm))
448         return -1;
449     }
450
451   *tp = tm;
452   return t;
453 }
454
455
456 /* FIXME: This should use a signed type wide enough to hold any UTC
457    offset in seconds.  'int' should be good enough for GNU code.  We
458    can't fix this unilaterally though, as other modules invoke
459    __mktime_internal.  */
460 static time_t localtime_offset;
461
462 /* Convert *TP to a time_t value.  */
463 time_t
464 mktime (struct tm *tp)
465 {
466 #ifdef _LIBC
467   /* POSIX.1 8.1.1 requires that whenever mktime() is called, the
468      time zone names contained in the external variable `tzname' shall
469      be set as if the tzset() function had been called.  */
470   __tzset ();
471 #endif
472
473   return __mktime_internal (tp, __localtime_r, &localtime_offset);
474 }
475
476 #ifdef weak_alias
477 weak_alias (mktime, timelocal)
478 #endif
479
480 #ifdef _LIBC
481 libc_hidden_def (mktime)
482 libc_hidden_weak (timelocal)
483 #endif
484 \f
485 #if DEBUG
486
487 static int
488 not_equal_tm (const struct tm *a, const struct tm *b)
489 {
490   return ((a->tm_sec ^ b->tm_sec)
491           | (a->tm_min ^ b->tm_min)
492           | (a->tm_hour ^ b->tm_hour)
493           | (a->tm_mday ^ b->tm_mday)
494           | (a->tm_mon ^ b->tm_mon)
495           | (a->tm_year ^ b->tm_year)
496           | (a->tm_mday ^ b->tm_mday)
497           | (a->tm_yday ^ b->tm_yday)
498           | (a->tm_isdst ^ b->tm_isdst));
499 }
500
501 static void
502 print_tm (const struct tm *tp)
503 {
504   if (tp)
505     printf ("%04d-%02d-%02d %02d:%02d:%02d yday %03d wday %d isdst %d",
506             tp->tm_year + TM_YEAR_BASE, tp->tm_mon + 1, tp->tm_mday,
507             tp->tm_hour, tp->tm_min, tp->tm_sec,
508             tp->tm_yday, tp->tm_wday, tp->tm_isdst);
509   else
510     printf ("0");
511 }
512
513 static int
514 check_result (time_t tk, struct tm tmk, time_t tl, const struct tm *lt)
515 {
516   if (tk != tl || !lt || not_equal_tm (&tmk, lt))
517     {
518       printf ("mktime (");
519       print_tm (lt);
520       printf (")\nyields (");
521       print_tm (&tmk);
522       printf (") == %ld, should be %ld\n", (long int) tk, (long int) tl);
523       return 1;
524     }
525
526   return 0;
527 }
528
529 int
530 main (int argc, char **argv)
531 {
532   int status = 0;
533   struct tm tm, tmk, tml;
534   struct tm *lt;
535   time_t tk, tl, tl1;
536   char trailer;
537
538   if ((argc == 3 || argc == 4)
539       && (sscanf (argv[1], "%d-%d-%d%c",
540                   &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &trailer)
541           == 3)
542       && (sscanf (argv[2], "%d:%d:%d%c",
543                   &tm.tm_hour, &tm.tm_min, &tm.tm_sec, &trailer)
544           == 3))
545     {
546       tm.tm_year -= TM_YEAR_BASE;
547       tm.tm_mon--;
548       tm.tm_isdst = argc == 3 ? -1 : atoi (argv[3]);
549       tmk = tm;
550       tl = mktime (&tmk);
551       lt = localtime (&tl);
552       if (lt)
553         {
554           tml = *lt;
555           lt = &tml;
556         }
557       printf ("mktime returns %ld == ", (long int) tl);
558       print_tm (&tmk);
559       printf ("\n");
560       status = check_result (tl, tmk, tl, lt);
561     }
562   else if (argc == 4 || (argc == 5 && strcmp (argv[4], "-") == 0))
563     {
564       time_t from = atol (argv[1]);
565       time_t by = atol (argv[2]);
566       time_t to = atol (argv[3]);
567
568       if (argc == 4)
569         for (tl = from; by < 0 ? to <= tl : tl <= to; tl = tl1)
570           {
571             lt = localtime (&tl);
572             if (lt)
573               {
574                 tmk = tml = *lt;
575                 tk = mktime (&tmk);
576                 status |= check_result (tk, tmk, tl, &tml);
577               }
578             else
579               {
580                 printf ("localtime (%ld) yields 0\n", (long int) tl);
581                 status = 1;
582               }
583             tl1 = tl + by;
584             if ((tl1 < tl) != (by < 0))
585               break;
586           }
587       else
588         for (tl = from; by < 0 ? to <= tl : tl <= to; tl = tl1)
589           {
590             /* Null benchmark.  */
591             lt = localtime (&tl);
592             if (lt)
593               {
594                 tmk = tml = *lt;
595                 tk = tl;
596                 status |= check_result (tk, tmk, tl, &tml);
597               }
598             else
599               {
600                 printf ("localtime (%ld) yields 0\n", (long int) tl);
601                 status = 1;
602               }
603             tl1 = tl + by;
604             if ((tl1 < tl) != (by < 0))
605               break;
606           }
607     }
608   else
609     printf ("Usage:\
610 \t%s YYYY-MM-DD HH:MM:SS [ISDST] # Test given time.\n\
611 \t%s FROM BY TO # Test values FROM, FROM+BY, ..., TO.\n\
612 \t%s FROM BY TO - # Do not test those values (for benchmark).\n",
613             argv[0], argv[0], argv[0]);
614
615   return status;
616 }
617
618 #endif /* DEBUG */
619 \f
620 /*
621 Local Variables:
622 compile-command: "gcc -DDEBUG -Wall -W -O -g mktime.c -o mktime"
623 End:
624 */