Branch: Tag:

2004-12-14

2004-12-14 16:22:00 by Martin Stjernholm <mast@lysator.liu.se>

Corrected f_mktime for some combinations of HAVE_MKTIME, HAVE_GMTIME and
HAVE_LOCALTIME. Make the timezone correction even when my_time_inverse is
used with localtime as replacement for gmtime. Disabled the "fix" for the
allegedly broken Linux mktime(3) since the fix itself is broken.

Rev: src/builtin_functions.c:1.473

2:   || This file is part of Pike. For copyright information see COPYRIGHT.   || Pike is distributed under GPL, LGPL and MPL. See the file COPYING   || for more information. - || $Id: builtin_functions.c,v 1.472 2004/12/14 15:04:57 mast Exp $ + || $Id: builtin_functions.c,v 1.473 2004/12/14 16:22:00 mast Exp $   */      #include "global.h" - RCSID("$Id: builtin_functions.c,v 1.472 2004/12/14 15:04:57 mast Exp $"); + RCSID("$Id: builtin_functions.c,v 1.473 2004/12/14 16:22:00 mast Exp $");   #include "interpret.h"   #include "svalue.h"   #include "pike_macros.h"
4182: Inside #if defined (HAVE_GMTIME) || defined (HAVE_LOCALTIME)
     typedef struct tm *time_fn (const time_t *);    - /* Inverse operation of gmtime or localtime. + /* Inverse operation of gmtime or localtime. Unlike mktime(3), this +  * doesn't fill in a normalized time in target_tm.    */   static int my_time_inverse (struct tm *target_tm, time_t *result, time_fn timefn)   {
4388: Inside #if defined (HAVE_MKTIME) || defined (HAVE_LOCALTIME)
  #endif /* HAVE_GMTIME */       { - #ifdef HAVE_MKTIME -  +    #ifdef STRUCT_TM_HAS_GMTOFF    /* BSD-style */    date.tm_gmtoff = 0;
4415:   #endif /* STRUCT_TM_HAS___TM_GMTOFF */   #endif /* STRUCT_TM_HAS_GMTOFF */    + #ifdef HAVE_MKTIME    retval = mktime(&date); -  +  if (retval == -1) + #endif +  { + #ifdef HAVE_LOCALTIME +  /* mktime might fail on dates before 1970 (e.g. GNU libc 2.3.2), +  * so try our own inverse function with localtime. */ +  if (!my_time_inverse (&date, &retval, localtime)) + #endif +  PIKE_ERROR("mktime", "Time conversion unsuccessful.\n", Pike_sp, args); +  }    -  if (retval != -1) { +    #if defined(STRUCT_TM_HAS_GMTOFF) || defined(STRUCT_TM_HAS___TM_GMTOFF)    if((args > 7) && (Pike_sp[7-args].subtype == NUMBER_NUMBER))    {
4434:    retval += Pike_sp[7-args].u.integer + date.__tm_gmtoff;   #endif /* STRUCT_TM_HAS_GMTOFF */    } + #endif /* STRUCT_TM_HAS_GMTOFF || STRUCT_TM_HAS___TM_GMTOFF */    -  + #if 0 +  /* Disabled since the adjustment done here with a hardcoded one +  * hour is bogus in many time zones. mktime(3) in GNU libc is +  * documented to normalize the date spec, which means that e.g. +  * asking for DST time in a non-DST zone will override tm_isdst. +  * /mast */    if ((args > 6) && (Pike_sp[6-args].subtype == NUMBER_NUMBER) &&    (Pike_sp[6-args].u.integer != -1) &&    (Pike_sp[6-args].u.integer != date.tm_isdst)) {    /* Some stupid libc's (Hi Linux!) don't accept that we've set isdst... */ - #ifdef HAVE_LOCALTIME -  if (!my_time_inverse (&date, &retval, localtime)) -  PIKE_ERROR("mktime", "Time conversion unsuccessful.\n", Pike_sp, args); - #else -  /* Last resort: Assumes a one hour DST. */ +     retval += 3600 * (Pike_sp[6-args].u.integer - date.tm_isdst); - #endif +     } - #endif /* STRUCT_TM_HAS_GMTOFF || STRUCT_TM_HAS___TM_GMTOFF */ + #endif /* 0 */    } -  else - #endif /* HAVE_MKTIME */ +     -  { - #ifdef HAVE_LOCALTIME -  /* mktime might fail on dates before 1970 (GNU libc 2.3.2), so -  * try our own inverse function with localtime. */ -  if (!my_time_inverse (&date, &retval, localtime)) - #endif -  PIKE_ERROR("mktime", "Time conversion unsuccessful.\n", Pike_sp, args); -  } -  } -  +     pop_n_elems(args);    push_int(retval);   }