?RCS: $Id$
?RCS:
?RCS: Copyright (c) 2008 H.Merijn Brand
?RCS:
?RCS: You may distribute under the terms of either the GNU General Public
?RCS: License or the Artistic License, as specified in the README file.
?RCS:
?MAKE:sGMTIME_max sGMTIME_min sLOCALTIME_max sLOCALTIME_min: cat rm_try \
	Setvar Compile run
?MAKE:	-pick add $@ %<
?S:sGMTIME_max:
?S:	This variable defines the maximum value of the time_t offset that
?S:	the system function gmtime () accepts
?S:.
?S:sGMTIME_min:
?S:	This variable defines the minimum value of the time_t offset that
?S:	the system function gmtime () accepts
?S:.
?S:sLOCALTIME_max:
?S:	This variable defines the maximum value of the time_t offset that
?S:	the system function localtime () accepts
?S:.
?S:sLOCALTIME_min:
?S:	This variable defines the minimum value of the time_t offset that
?S:	the system function localtime () accepts
?S:.
?C:GMTIME_MAX:
?C:	This symbol contains the maximum value for the time_t offset that
?C:	the system function gmtime () accepts, and defaults to 0
?C:.
?C:GMTIME_MIN:
?C:	This symbol contains the minimum value for the time_t offset that
?C:	the system function gmtime () accepts, and defaults to 0
?C:.
?C:LOCALTIME_MAX:
?C:	This symbol contains the maximum value for the time_t offset that
?C:	the system function localtime () accepts, and defaults to 0
?C:.
?C:LOCALTIME_MIN:
?C:	This symbol contains the minimum value for the time_t offset that
?C:	the system function localtime () accepts, and defaults to 0
?C:.
?H:#define GMTIME_MAX		$sGMTIME_max	/**/
?H:#define GMTIME_MIN		$sGMTIME_min	/**/
?H:#define LOCALTIME_MAX	$sLOCALTIME_max	/**/
?H:#define LOCALTIME_MIN	$sLOCALTIME_min	/**/
?H:.
?D:sGMTIME_max=0
?D:sGMTIME_min=0
?D:sLOCALTIME_max=0
?D:sLOCALTIME_min=0
?F:!try
: Check the max offset that gmtime and localtime accept
echo "Checking max offsets that gmtime () accepts"

case "$sGMTIME_min/$sGMTIME_max" in
    0/0|/)
	$cat >try.c <<EOCP
#include <sys/types.h>
#include <stdio.h>
#include <time.h>

int i;
struct tm *tmp;
time_t pt;

void gm_check (time_t t, int min_year, int max_year)
{
    tmp = gmtime (&t);
    if ( tmp == NULL ||
	/* Check tm_year overflow */
	 tmp->tm_year < min_year || tmp->tm_year > max_year)
	tmp = NULL;
    else
	pt = t;
    } /* gm_check */

int check_max ()
{
    tmp = NULL;
    pt  = 0;
#ifdef MAXLONG
    gm_check (MAXLONG, 69, 0x7fffffff);
#endif
    if (tmp == NULL || tmp->tm_year < 0) {
	for (i = 63; i >= 0; i--) {
	    time_t x = pt | ((time_t)1 << i);
	    if (x < 0 || x < pt) continue;
	    gm_check (x, 69, 0x7fffffff);
	    }
	}
    printf ("sGMTIME_max=%ld\n", pt);
    return (0);
    } /* check_max */

int check_min ()
{
    tmp = NULL;
    pt  = 0;
#ifdef MINLONG
    gm_check (MINLONG, -1900, 70);
#endif
    if (tmp == NULL) {
	for (i = 36; i >= 0; i--) {
	    time_t x = pt - ((time_t)1 << i);
	    if (x > 0) continue;
	    gm_check (x, -1900, 70);
	    }
	}
    printf ("sGMTIME_min=%ld\n", pt);
    return (0);
    } /* check_min */

int main (int argc, char *argv[])
{
    /* fprintf (stderr, "Sizeof time_t = %ld\n", sizeof (time_t)); */
    check_max ();
    check_min ();
    return (0);
    } /* main */
EOCP
	set try
	if eval $compile; then
	    eval `$run ./try 2>/dev/null`
	else
	    echo "Cannot determine sGMTIME_max and sGMTIME_min." >&4
	    fi
	$rm_try
	;;
    esac

echo "Checking max offsets that localtime () accepts"

case "$sLOCALTIME_min/$sLOCALTIME_max" in
    0/0|/)
	$cat >try.c <<EOCP
#include <sys/types.h>
#include <stdio.h>
#include <time.h>

int i;
struct tm *tmp;
time_t pt;

void local_check (time_t t, int min_year, int max_year)
{
    if (sizeof (time_t) > 4 && t > 0x7ffffffffffff000LL)
	tmp = NULL;
    else
	tmp = localtime (&t);
    if ( tmp == NULL ||
	/* Check tm_year overflow */
	 tmp->tm_year < min_year || tmp->tm_year > max_year)
	tmp = NULL;
    else
	pt = t;
    } /* local_check */

int check_max ()
{
    tmp = NULL;
    pt  = 0;
#ifdef MAXLONG
    local_check (MAXLONG, 69, 0x7fffffff);
#endif
    if (tmp == NULL || tmp->tm_year < 0) {
	for (i = 63; i >= 0; i--) {
	    time_t x = pt | ((time_t)1 << i);
	    if (x < 0 || x < pt) continue;
	    local_check (x, 69, 0x7fffffff);
	    }
	}
    printf ("sLOCALTIME_max=%ld\n", pt);
    return (0);
   } /* check_max */

int check_min ()
{
    tmp = NULL;
    pt  = 0;
#ifdef MINLONG
    local_check (MINLONG, -1900, 70);
#endif
    if (tmp == NULL) {
	for (i = 36; i >= 0; i--) {
	    time_t x = pt - ((time_t)1 << i);
	    if (x > 0) continue;
	    local_check (x, -1900, 70);
	    }
	}
    printf ("sLOCALTIME_min=%ld\n", pt);
    return (0);
    } /* check_min */

int main (int argc, char *argv[])
{
    check_max ();
    check_min ();
    return (0);
    } /* main */
EOCP
	set try
	if eval $compile; then
	    eval `$run ./try 2>/dev/null`
	else
	    echo "Cannot determine sLOCALTIME_max and sLOCALTIME_min." >&4
	    fi
	$rm_try
	;;
    esac

