bug-cvs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Bug-gnulib] Re: CVS trunk testing results (PowerBook G4 MacOS X - 1


From: Mark D. Baushke
Subject: Re: [Bug-gnulib] Re: CVS trunk testing results (PowerBook G4 MacOS X - 10.2.8)
Date: Wed, 10 Nov 2004 14:12:18 -0800

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Paul Eggert <eggert@CS.UCLA.EDU> writes:

> Derek Robert Price <derek@ximbiot.com> writes:
> 
> > The getdate.y module is failing near the UNIX epoch on Mac OS X, but
> > only when TZ=UTC.
> 
> First, does TZ="UTC" even work at all?

Yes.

> POSIX says that you have to TZ="UTC0", and that the behavior of
> TZ="UTC" is undefined. Most implementations I'm familiar with (glibc,
> Olson, Solaris) treat unknown time zones as if they were UTC, but if
> Mac OS X is using their own implementation perhaps it screws up in
> some cases. Your bug report also talks about setting TZ="-0800" but
> this also has undefined behavior.

When TZ is not defined, the default system timze zone is "-0800" which
prints PST.

> > For example, entering either "1970-01-01 2:00:00 -0400" or
> > "1970-01-01 2:00:00 +0400" with TZ=UTC on OS X will yield the output
> > "1970-01-01 02:00:00.000000000", which I would hazard is obviously
> > incorrect for any single given local timezone.
> 
> Yes, you're right.  If the time zone offset is specified explicitly,
> which is the case here, then TZ should be irrelevant.

$ ./getdate
Enter date, or blank line to exit.
        > 1970-01-01 2:00:00 -0400
1970-01-01 06:00:00.000000000
        > "1970-01-01 2:00:00 +0400
Bad format - couldn't convert.
        > ^D
$

> > Has anyone heard of anything like this before?
> 
> No.
> 
> > rereading of the complex getdate.y code hasn't given me any
> > inspiration.
> 
> Is your implementation using Mac OS X mktime, or gnulib mktime?

GNULIB mktime

> What is the value of HAVE_TM_GMTOFF?  

$ grep HAVE_TM_GMTOFF ../config.h
#define HAVE_TM_GMTOFF 1
$ 

> If it is 1 and if you are using Mac OS X mktime, perhaps Mac OS X
> mktime is returning a bogus value in the tm_gmtoff member when
> TZ="UTC". That might explain the bug. Can you put a breakpoint on line
> 1285 of getdate.y ("if (pc.zones_seen)") and single-step through each
> statement in the then-part of that if statement, and tell us what
> value got assigned in each assignment?

gdb getdate
GNU gdb 5.3-20021014 (Apple version gdb-250) (Sat Dec  7 02:14:27 GMT 2002)
Copyright 2002 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "powerpc-apple-macos10".
Reading symbols for shared libraries ... done
(gdb) b 1285
Breakpoint 1 at 0x3f88: file getdate.y, line 1285.
(gdb) list 1285
1280    getdate.y: No such file or directory.
        in getdate.y
(gdb) dir ../../lib
Source directories searched: 
/Users/mdb/src/cvs/ccvs-trunk/ccvs.debug/obj.macosx/lib/../../lib:$cdir:$cwd
(gdb) list 1285
1280              Start = mktime (&tm);
1281              if (Start == (time_t) -1)
1282                goto fail;
1283            }
1284
1285          if (pc.zones_seen)
1286            {
1287              long int delta = pc.time_zone * 60;
1288              time_t t1;
1289    #ifdef HAVE_TM_GMTOFF
(gdb) run
Starting program: 
/Users/mdb/src/cvs/ccvs-trunk/ccvs.debug/obj.macosx/lib/getdate 
[Switching to process 10123 thread 0xb03]
Reading symbols for shared libraries . done
Reading symbols for shared libraries ................ done
Enter date, or blank line to exit.
        > 1970-01-01 2:00:00 -0400

Breakpoint 1, get_date (result=0xbffffac0, p=0xbffff420 "", now=0x1c20) at 
getdate.y:1285
1285          if (pc.zones_seen)
(gdb)  p pc
$1 = {
  input = 0xbffff6da "ð", 
  day_ordinal = -1073744192, 
  day_number = -1610609452, 
  local_isdst = -1073744192, 
  time_zone = -240, 
  meridian = 2, 
  year = {
    value = 1970, 
    digits = 4
  }, 
  month = 1, 
  day = 1, 
  hour = 2, 
  minutes = 0, 
  seconds = {
    tv_sec = 0, 
    tv_nsec = 0
  }, 
  rel_year = 0, 
  rel_month = 0, 
  rel_day = 0, 
  rel_hour = 0, 
  rel_minutes = 0, 
  rel_seconds = 0, 
  rel_ns = 0, 
  timespec_seen = false, 
  dates_seen = 1, 
  days_seen = 0, 
  local_zones_seen = 0, 
  rels_seen = 0, 
  times_seen = 1, 
  zones_seen = 1, 
  local_time_zone_table = {{
      name = 0xaba1c "UTC", 
      type = 264, 
      value = 0
    }, {
      name = 0x0, 
      type = 0, 
      value = -1073744192
    }, {
      name = 0xa0000cd4 "", 
      type = -1073744192, 
      value = 131072
    }}
}
(gdb) p pc.zones_seen
$2 = 1
(gdb) b mktime
Breakpoint 2 at 0x9006ba94



(gdb) b mktime
Breakpoint 1 at 0x9006ba94
(gdb) run
Starting program: 
/Users/mdb/src/cvs/ccvs-trunk/ccvs.debug/obj.macosx/lib/getdate 
[Switching to process 10129 thread 0xb03]
Reading symbols for shared libraries . done
Reading symbols for shared libraries ................ done
Enter date, or blank line to exit.
        > 1970-01-01 2:00:00 -0400
1970-01-01 06:00:00.000000000
        > 

Hmmm... it does not seem to have stopped at mktime along the way... :-(

...

(gdb) cont
Continuing.
1970-01-01 06:00:00.000000000
        > 1970-01-01 2:00:00 -0400

Breakpoint 2, get_date (result=0xbffffac0, p=0xbffff420 "", now=0x1c20) at 
getdate.y:1285
1285          if (pc.zones_seen)
(gdb) n
1287              long int delta = pc.time_zone * 60;
(gdb) n
1299              if ((Start < t1) != (delta < 0))
(gdb) p delta
$1 = -240
(gdb) n
1290              delta -= tm.tm_gmtoff;
(gdb) p delta
$2 = -240
(gdb) p tm
$3 = {
  tm_sec = 0, 
  tm_min = 0, 
  tm_hour = 2, 
  tm_mday = 1, 
  tm_mon = 0, 
  tm_year = 70, 
  tm_wday = 4, 
  tm_yday = 0, 
  tm_isdst = 0, 
  tm_gmtoff = 0, 
  tm_zone = 0xaba1c "UTC"
}
(gdb) p t1
$4 = 0
(gdb) n
1287              long int delta = pc.time_zone * 60;
(gdb) n
1290              delta -= tm.tm_gmtoff;
(gdb) p Start
$5 = 7200
(gdb) n
1298              t1 = Start - delta;
(gdb) n
1299              if ((Start < t1) != (delta < 0))
(gdb) p t1
$6 = 21600
(gdb) p delta
$7 = -14400
(gdb) p Start
$8 = 7200
(gdb) c
Continuing.
1970-01-01 06:00:00.000000000
        > 


> Also, can you give us a trace of all calls to mktime, what the input
> values were, and what the returned value and the resulting struct tm
> was?  That might help us narrow it down.
> 
> For example, try reproducing the following GDB session and see where
> your results diverge from mine.
> 
> Current directory is /tmp/
> GNU gdb 2002-04-01-cvs
> Copyright 2002 Free Software Foundation, Inc.
> GDB is free software, covered by the GNU General Public License, and you are
> welcome to change it and/or distribute copies of it under certain conditions.
> Type "show copying" to see the conditions.
> There is absolutely no warranty for GDB.  Type "show warranty" for details.
> This GDB was configured as "i386-linux"...
> (gdb) b main
> Breakpoint 1 at 0x804b1e9: file getdate.y, line 1374.
> (gdb) set env TZ UTC0
> (gdb) r
> Starting program: /tmp/getdate 
> [New Thread 1024 (LWP 15596)]
> [Switching to Thread 1024 (LWP 15596)]
> 
> Breakpoint 1, main (ac=1, av=0xbffffa24) at getdate.y:1374
> (gdb) b getdate.y:1285
> Breakpoint 2 at 0x804ad73: file getdate.y, line 1285.
> (gdb) b mktime
> Breakpoint 3 at 0x804bdf0: file mktime.c, line 480.
> (gdb) c
> Continuing.
> Enter date, or blank line to exit.
>       > 1970-01-01 2:00:00 -0400
> 
> Breakpoint 3, mktime (tp=0xbfffd910) at mktime.c:480
> (gdb) p *tp
> $1 = {tm_sec = 0, tm_min = 0, tm_hour = 2, tm_mday = 1, tm_mon = 0, tm_year = 
> 70, tm_wday = 1075069056, 
>   tm_yday = 1074333038, tm_isdst = -1, tm_gmtoff = 1073821132, tm_zone = 
> 0xbffffa24 "\211.�."}
> (gdb) fin
> Run till exit from #0  mktime (tp=0xbfffd910) at mktime.c:480
> 0x0804ab49 in get_date (result=0xbfffd9ac, p=0xbfffd9b4 "1970-01-01 2:00:00 
> -0400\n", now=0xbfffd838)
>     at getdate.y:1237
> Value returned is $2 = 7200
> (gdb) p tm
> $3 = {tm_sec = 0, tm_min = 0, tm_hour = 2, tm_mday = 1, tm_mon = 0, tm_year = 
> 70, tm_wday = 4, tm_yday = 0, 
>   tm_isdst = 0, tm_gmtoff = 0, tm_zone = 0x804d1d0 "UTC"}
> (gdb) c
> Continuing.
> 
> Breakpoint 2, get_date (result=0xbfffd9ac, p=0xbfffd9b4 "1970-01-01 2:00:00 
> -0400\n", now=0xbfffd838)
>     at getdate.y:1285
> (gdb) n
> (gdb) n
> (gdb) p delta
> $4 = -14400
> (gdb) n
> (gdb) p delta
> $5 = -14400
> (gdb) n
> (gdb) p t1
> $6 = 21600
> (gdb) n
> (gdb) n
> (gdb) p Start
> $7 = 21600
> (gdb) c
> Continuing.
> 1970-01-01 06:00:00.000000000

The version of cpp output of the mktime file is after my .signature.

        -- Mark

$ gcc -DHAVE_CONFIG_H -I. -I../../lib -I.. -I/sw/include -Ino/include -g \
 -O2 -E ../../lib/mktime.c > mktime.i
# 1 "../../lib/mktime.c"

# 25
# 1 "../config.h" 1 3

# 25 "../../lib/mktime.c" 2










# 1 "/usr/include/sys/types.h" 1 3

# 66
# 1 "/usr/include/sys/appleapiopts.h" 1 3

# 66 "/usr/include/sys/types.h" 2 3



# 1 "/usr/include/sys/cdefs.h" 1 3

# 69 "/usr/include/sys/types.h" 2 3



# 1 "/usr/include/machine/types.h" 1 3

# 30
# 1 "/usr/include/ppc/types.h" 1

# 69
typedef signed char int8_t ; 
typedef unsigned char u_int8_t ; 
typedef short int16_t ; 
typedef unsigned short u_int16_t ; 
typedef int int32_t ; 
typedef unsigned int u_int32_t ; 
typedef long long int64_t ; 
typedef unsigned long long u_int64_t ; 

typedef int32_t register_t ; 

typedef long int intptr_t ; 
typedef unsigned long int uintptr_t ; 
# 30 "/usr/include/machine/types.h" 2 3

# 72 "/usr/include/sys/types.h" 2 3


# 1 "/usr/include/machine/ansi.h" 1 3

# 33
# 1 "/usr/include/ppc/ansi.h" 1

# 92
typedef union { 
char __mbstate8 [ 128 ] ; 
long long _mbstateL ; 
} __mbstate_t ; 
# 33 "/usr/include/machine/ansi.h" 2 3

# 74 "/usr/include/sys/types.h" 2 3

# 1 "/usr/include/machine/endian.h" 1 3

# 30
# 1 "/usr/include/ppc/endian.h" 1

# 82
unsigned long htonl ( unsigned long ) ; 
unsigned short htons ( unsigned short ) ; 
unsigned long ntohl ( unsigned long ) ; 
unsigned short ntohs ( unsigned short ) ; 
# 30 "/usr/include/machine/endian.h" 2 3

# 75 "/usr/include/sys/types.h" 2 3



typedef unsigned char u_char ; 
typedef unsigned short u_short ; 
typedef unsigned int u_int ; 
typedef unsigned long u_long ; 
typedef unsigned short ushort ; 
typedef unsigned int uint ; 


typedef u_int64_t u_quad_t ; 
typedef int64_t quad_t ; 
typedef quad_t * qaddr_t ; 

typedef char * caddr_t ; 
typedef int32_t daddr_t ; 
typedef int32_t dev_t ; 
typedef u_int32_t fixpt_t ; 
typedef u_int32_t gid_t ; 
typedef u_int32_t in_addr_t ; 
typedef u_int16_t in_port_t ; 
typedef u_int32_t ino_t ; 
typedef long key_t ; 
typedef u_int16_t mode_t ; 
typedef u_int16_t nlink_t ; 
typedef quad_t off_t ; 
typedef int32_t pid_t ; 
typedef quad_t rlim_t ; 
typedef int32_t segsz_t ; 
typedef int32_t swblk_t ; 
typedef u_int32_t uid_t ; 










typedef unsigned long clock_t ; 




typedef long unsigned int size_t ; 




typedef int ssize_t ; 




typedef long time_t ; 













typedef int32_t fd_mask ; 






typedef struct fd_set { 
fd_mask fds_bits [ ( ( ( 1024 ) + ( ( ( sizeof ( fd_mask ) * 8 ) ) - 1 ) ) / ( 
( sizeof ( fd_mask ) * 8 ) ) ) ] ; 
} fd_set ; 
# 182
struct _pthread_handler_rec 
{ 
void ( * routine ) ( void * ) ; 
void * arg ; 
struct _pthread_handler_rec * next ; 
} ; 














typedef struct _opaque_pthread_t { long sig ; struct _pthread_handler_rec * 
cleanup_stack ; char opaque [ 596 ] ; } * pthread_t ; 

typedef struct _opaque_pthread_attr_t { long sig ; char opaque [ 36 ] ; } 
pthread_attr_t ; 

typedef struct _opaque_pthread_mutexattr_t { long sig ; char opaque [ 8 ] ; } 
pthread_mutexattr_t ; 

typedef struct _opaque_pthread_mutex_t { long sig ; char opaque [ 40 ] ; } 
pthread_mutex_t ; 

typedef struct _opaque_pthread_condattr_t { long sig ; char opaque [ 4 ] ; } 
pthread_condattr_t ; 

typedef struct _opaque_pthread_cond_t { long sig ; char opaque [ 24 ] ; } 
pthread_cond_t ; 

typedef struct _opaque_pthread_rwlockattr_t { long sig ; char opaque [ 12 ] ; } 
pthread_rwlockattr_t ; 

typedef struct _opaque_pthread_rwlock_t { long sig ; char opaque [ 124 ] ; } 
pthread_rwlock_t ; 

typedef struct { long sig ; char opaque [ 4 ] ; } pthread_once_t ; 



typedef unsigned long pthread_key_t ; 
# 35 "../../lib/mktime.c" 2

# 1 "/usr/include/time.h" 1 3

# 88
struct timespec { 
time_t tv_sec ; 
long tv_nsec ; 
} ; 


struct tm { 
int tm_sec ; 
int tm_min ; 
int tm_hour ; 
int tm_mday ; 
int tm_mon ; 
int tm_year ; 
int tm_wday ; 
int tm_yday ; 
int tm_isdst ; 
long tm_gmtoff ; 
char * tm_zone ; 
} ; 

# 1 "/usr/include/gcc/darwin/3.1/machine/limits.h" 1 3





# 1 "/usr/include/ppc/limits.h" 1 3

# 6 "/usr/include/gcc/darwin/3.1/machine/limits.h" 2 3

# 108 "/usr/include/time.h" 2 3







extern char * tzname [ ] ; 



char * asctime ( const struct tm * ) ; 
clock_t clock ( void ) ; 
char * ctime ( const time_t * ) ; 
double difftime ( time_t , time_t ) ; 
struct tm * gmtime ( const time_t * ) ; 
struct tm * localtime ( const time_t * ) ; 
time_t rpl_mktime ( struct tm * ) ; 
size_t strftime ( char * , size_t , const char * , const struct tm * ) ; 
time_t time ( time_t * ) ; 


void tzset ( void ) ; 



char * asctime_r ( const struct tm * , char * ) ; 
char * ctime_r ( const time_t * , char * ) ; 
struct tm * gmtime_r ( const time_t * , struct tm * ) ; 
struct tm * localtime_r ( const time_t * , struct tm * ) ; 
char * strptime ( const char * , const char * , struct tm * ) ; 
char * timezone ( int , int ) ; 
void tzsetwall ( void ) ; 
time_t timelocal ( struct tm * const ) ; 
time_t timegm ( struct tm * const ) ; 



int nanosleep ( const struct timespec * , struct timespec * ) ; 
# 36 "../../lib/mktime.c" 2


# 1 "/usr/include/limits.h" 1 3

# 63
# 1 "/usr/include/sys/syslimits.h" 1 3

# 63 "/usr/include/limits.h" 2 3

# 38 "../../lib/mktime.c" 2

# 67
struct time_t_is_integer { char a [ ( ( time_t ) 0.5 == 0 ) ? 1 : - 1 ] ; } ; 
struct twos_complement_arithmetic { char a [ ( - 1 == ~ 1 + 1 ) ? 1 : - 1 ] ; } 
; 
struct right_shift_propagates_sign { char a [ ( - 1 >> 1 == - 1 ) ? 1 : - 1 ] ; 
} ; 






struct base_year_is_a_multiple_of_100 { char a [ ( 1900 % 100 == 0 ) ? 1 : - 1 
] ; } ; 


static inline int 
leapyear ( long int year ) 
{ 


return 
( ( year & 3 ) == 0 
&& ( year % 100 != 0 
|| ( ( year / 100 ) & 3 ) == ( - ( 1900 / 100 ) & 3 ) ) ) ; 
} 



static 

const unsigned short int __mon_yday [ 2 ] [ 13 ] = 
{ 

{ 0 , 31 , 59 , 90 , 120 , 151 , 181 , 212 , 243 , 273 , 304 , 334 , 365 } , 

{ 0 , 31 , 60 , 91 , 121 , 152 , 182 , 213 , 244 , 274 , 305 , 335 , 366 } 
} ; 







# 1 "../../lib/time_r.h" 1

# 108 "../../lib/mktime.c" 2

















static inline time_t 
ydhms_diff ( long int year1 , long int yday1 , int hour1 , int min1 , int sec1 
, 
int year0 , int yday0 , int hour0 , int min0 , int sec0 ) 
{ 
struct C99_integer_division { char a [ ( - 1 / 2 == 0 ) ? 1 : - 1 ] ; } ; 
struct long_int_year_and_yday_are_wide_enough { char a [ ( 2147483647 <= 
2147483647L / 2 || ( ( time_t ) ( ~ ( time_t ) 0 - ( ( time_t ) ( ( ! ( ( 
time_t ) 0 < ( time_t ) - 1 ) ) ? ~ ( time_t ) 0 << ( sizeof ( time_t ) * 8 - 1 
) : ( time_t ) 0 ) ) ) ) <= ( 2147483647 * 2U + 1 ) ) ? 1 : - 1 ] ; } 
; 



int a4 = ( year1 >> 2 ) + ( 1900 >> 2 ) - ! ( year1 & 3 ) ; 
int b4 = ( year0 >> 2 ) + ( 1900 >> 2 ) - ! ( year0 & 3 ) ; 
int a100 = a4 / 25 - ( a4 % 25 < 0 ) ; 
int b100 = b4 / 25 - ( b4 % 25 < 0 ) ; 
int a400 = a100 >> 2 ; 
int b400 = b100 >> 2 ; 
int intervening_leap_days = ( a4 - b4 ) - ( a100 - b100 ) + ( a400 - b400 ) ; 



time_t tyear1 = year1 ; 
time_t years = tyear1 - year0 ; 
time_t days = 365 * years + yday1 - yday0 + intervening_leap_days ; 
time_t hours = 24 * days + hour1 - hour0 ; 
time_t minutes = 60 * hours + min1 - min0 ; 
time_t seconds = 60 * minutes + sec1 - sec0 ; 
return seconds ; 
} 








static time_t 
guess_time_tm ( long int year , long int yday , int hour , int min , int sec , 
const time_t * t , const struct tm * tp ) 
{ 
if ( tp ) 
{ 
time_t d = ydhms_diff ( year , yday , hour , min , sec , 
tp -> tm_year , tp -> tm_yday , 
tp -> tm_hour , tp -> tm_min , tp -> tm_sec ) ; 
time_t t1 = * t + d ; 
if ( ( t1 < * t ) == ( ( ! ( ( time_t ) 0 < ( time_t ) - 1 ) ) ? d < 0 : ( ( 
time_t ) ( ~ ( time_t ) 0 - ( ( time_t ) ( ( ! ( ( time_t ) 0 < ( time_t ) - 1 
) ) ? ~ ( time_t ) 0 << ( sizeof ( time_t ) * 8 - 1 ) : ( time_t ) 0 ) ) ) ) / 
2 < d ) ) 
return t1 ; 
} 





return ( * t < ( ( ( ( ( time_t ) ( ( ! ( ( time_t ) 0 < ( time_t ) - 1 ) ) ? ~ 
( time_t ) 0 << ( sizeof ( time_t ) * 8 - 1 ) : ( time_t ) 0 ) ) + ( ( time_t ) 
( ~ ( time_t ) 0 - ( ( time_t ) ( ( ! ( ( time_t ) 0 < ( time_t ) - 1 ) ) ? ~ ( 
time_t ) 0 << ( sizeof ( time_t ) * 8 - 1 ) : ( time_t ) 0 ) ) ) ) ) >> 1 ) + 1 
) 
? ( ( time_t ) ( ( ! ( ( time_t ) 0 < ( time_t ) - 1 ) ) ? ~ ( time_t ) 0 << ( 
sizeof ( time_t ) * 8 - 1 ) : ( time_t ) 0 ) ) + ( * t == ( ( time_t ) ( ( ! ( 
( time_t ) 0 < ( time_t ) - 1 ) ) ? ~ ( time_t ) 0 << ( sizeof ( time_t ) * 8 - 
1 ) : ( time_t ) 0 ) ) ) 
: ( ( time_t ) ( ~ ( time_t ) 0 - ( ( time_t ) ( ( ! ( ( time_t ) 0 < ( time_t 
) - 1 ) ) ? ~ ( time_t ) 0 << ( sizeof ( time_t ) * 8 - 1 ) : ( time_t ) 0 ) ) 
) ) - ( * t == ( ( time_t ) ( ~ ( time_t ) 0 - ( ( time_t ) ( ( ! ( ( time_t ) 
0 < ( time_t ) - 1 ) ) ? ~ ( time_t ) 0 << ( sizeof ( time_t ) * 8 - 1 ) : ( 
time_t ) 0 ) ) ) ) ) ) ; 
} 




static struct tm * 
ranged_convert ( struct tm * ( * convert ) ( const time_t * , struct tm * ) , 
time_t * t , struct tm * tp ) 
{ 
struct tm * r ; 

if ( ! ( r = ( * convert ) ( t , tp ) ) && * t ) 
{ 
time_t bad = * t ; 
time_t ok = 0 ; 
struct tm tm ; 




while ( bad != ok + ( bad < 0 ? - 1 : 1 ) ) 
{ 
time_t mid = * t = ( bad < 0 
? bad + ( ( ok - bad ) >> 1 ) 
: ok + ( ( bad - ok ) >> 1 ) ) ; 
if ( ( r = ( * convert ) ( t , tp ) ) ) 
{ 
tm = * r ; 
ok = mid ; 
} 
else 
bad = mid ; 
} 

if ( ! r && ok ) 
{ 


* t = ok ; 
* tp = tm ; 
r = tp ; 
} 
} 

return r ; 
} 








time_t 
mktime_internal ( struct tm * tp , 
struct tm * ( * convert ) ( const time_t * , struct tm * ) , 
time_t * offset ) 
{ 
time_t t , gt , t0 , t1 , t2 ; 
struct tm tm ; 





int remaining_probes = 6 ; 



int sec = tp -> tm_sec ; 
int min = tp -> tm_min ; 
int hour = tp -> tm_hour ; 
int mday = tp -> tm_mday ; 
int mon = tp -> tm_mon ; 
int year_requested = tp -> tm_year ; 
int isdst = tp -> tm_isdst ; 


int dst2 ; 


int mon_remainder = mon % 12 ; 
int negative_mon_remainder = mon_remainder < 0 ; 
int mon_years = mon / 12 - negative_mon_remainder ; 
long int lyear_requested = year_requested ; 
long int year = lyear_requested + mon_years ; 








int mon_yday = ( ( __mon_yday [ leapyear ( year ) ] 
[ mon_remainder + 12 * negative_mon_remainder ] ) 
- - 1 ) ; 
long int lmday = mday ; 
long int yday = mon_yday + lmday ; 

time_t guessed_offset = * offset ; 

int sec_requested = sec ; 

if ( 1 ) 
{ 


if ( sec < 0 ) 
sec = 0 ; 
if ( 59 < sec ) 
sec = 59 ; 
} 




t0 = ydhms_diff ( year , yday , hour , min , sec , 
1970 - 1900 , 0 , 0 , 0 , - guessed_offset ) ; 

if ( ( ( time_t ) ( ~ ( time_t ) 0 - ( ( time_t ) ( ( ! ( ( time_t ) 0 < ( 
time_t ) - 1 ) ) ? ~ ( time_t ) 0 << ( sizeof ( time_t ) * 8 - 1 ) : ( time_t ) 
0 ) ) ) ) / 2147483647 / 366 / 24 / 60 / 60 < 3 ) 
{ 












int ALOG2_SECONDS_PER_BIENNIUM = 26 ; 
int ALOG2_MINUTES_PER_BIENNIUM = 20 ; 
int ALOG2_HOURS_PER_BIENNIUM = 14 ; 
int ALOG2_DAYS_PER_BIENNIUM = 10 ; 
int LOG2_YEARS_PER_BIENNIUM = 1 ; 

int approx_requested_biennia = 
( ( year_requested >> LOG2_YEARS_PER_BIENNIUM ) 
- - ( ( 1970 - 1900 ) >> LOG2_YEARS_PER_BIENNIUM ) 
+ ( mday >> ALOG2_DAYS_PER_BIENNIUM ) 
+ ( hour >> ALOG2_HOURS_PER_BIENNIUM ) 
+ ( min >> ALOG2_MINUTES_PER_BIENNIUM ) 
+ ( 1 ? 0 : sec >> ALOG2_SECONDS_PER_BIENNIUM ) ) ; 

int approx_biennia = t0 >> ALOG2_SECONDS_PER_BIENNIUM ; 
int diff = approx_biennia - approx_requested_biennia ; 
int abs_diff = diff < 0 ? - diff : diff ; 





time_t time_t_max = ( ( time_t ) ( ~ ( time_t ) 0 - ( ( time_t ) ( ( ! ( ( 
time_t ) 0 < ( time_t ) - 1 ) ) ? ~ ( time_t ) 0 << ( sizeof ( time_t ) * 8 - 1 
) : ( time_t ) 0 ) ) ) ) ; 
time_t time_t_min = ( ( time_t ) ( ( ! ( ( time_t ) 0 < ( time_t ) - 1 ) ) ? ~ 
( time_t ) 0 << ( sizeof ( time_t ) * 8 - 1 ) : ( time_t ) 0 ) ) ; 
time_t overflow_threshold = 
( time_t_max / 3 - time_t_min / 3 ) >> ALOG2_SECONDS_PER_BIENNIUM ; 

if ( overflow_threshold < abs_diff ) 
{ 


time_t repaired_t0 = - 1 - t0 ; 
approx_biennia = repaired_t0 >> ALOG2_SECONDS_PER_BIENNIUM ; 
diff = approx_biennia - approx_requested_biennia ; 
abs_diff = diff < 0 ? - diff : diff ; 
if ( overflow_threshold < abs_diff ) 
return - 1 ; 
guessed_offset += repaired_t0 - t0 ; 
t0 = repaired_t0 ; 
} 
} 



for ( t = t1 = t2 = t0 , dst2 = 0 ; 
( gt = guess_time_tm ( year , yday , hour , min , sec , & t , 
ranged_convert ( convert , & t , & tm ) ) , 
t != gt ) ; 
t1 = t2 , t2 = t , t = gt , dst2 = tm . tm_isdst != 0 ) 
if ( t == t1 && t != t2 
&& ( tm . tm_isdst < 0 
|| ( isdst < 0 
? dst2 <= ( tm . tm_isdst != 0 ) 
: ( isdst != 0 ) != ( tm . tm_isdst != 0 ) ) ) ) 









goto offset_found ; 
else if ( -- remaining_probes == 0 ) 
return - 1 ; 



if ( isdst != tm . tm_isdst && 0 <= isdst && 0 <= tm . tm_isdst ) 
{ 














int stride = 601200 ; 






int duration_max = 536454000 ; 



int delta_bound = duration_max / 2 + stride ; 

int delta , direction ; 

for ( delta = stride ; delta < delta_bound ; delta += stride ) 
for ( direction = - 1 ; direction <= 1 ; direction += 2 ) 
{ 
time_t ot = t + delta * direction ; 
if ( ( ot < t ) == ( direction < 0 ) ) 
{ 
struct tm otm ; 
ranged_convert ( convert , & ot , & otm ) ; 
if ( otm . tm_isdst == isdst ) 
{ 


t = guess_time_tm ( year , yday , hour , min , sec , & ot , & otm ) ; 
ranged_convert ( convert , & t , & tm ) ; 
goto offset_found ; 
} 
} 
} 
} 

offset_found : 
* offset = guessed_offset + t - t0 ; 

if ( 1 && sec_requested != tm . tm_sec ) 
{ 


int sec_adjustment = ( sec == 0 && tm . tm_sec == 60 ) - sec ; 
t1 = t + sec_requested ; 
t2 = t1 + sec_adjustment ; 
if ( ( ( t1 < t ) != ( sec_requested < 0 ) ) 
| ( ( t2 < t1 ) != ( sec_adjustment < 0 ) ) 
| ! ( * convert ) ( & t , & tm ) ) 
return - 1 ; 
} 

* tp = tm ; 
return t ; 
} 






static time_t localtime_offset ; 


time_t 
rpl_mktime ( struct tm * tp ) 
{ 







return mktime_internal ( tp , localtime_r , & localtime_offset ) ; 
} 
# 626
/* end of message */
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.3 (FreeBSD)

iD8DBQFBkpJC3x41pRYZE/gRAn9MAKCMZu6usjXijHUZ0EYqlC7/YVVBEgCfXuW2
bjG1mcpeSymWuYFuka5NBbU=
=wF4B
-----END PGP SIGNATURE-----




reply via email to

[Prev in Thread] Current Thread [Next in Thread]