Mon Mar 31 07:41:15 2008

Asterisk developer's documentation


localtime.c File Reference

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <float.h>
#include "private.h"
#include "tzfile.h"
#include "asterisk.h"
#include "asterisk/lock.h"
#include "asterisk/localtime.h"
#include "asterisk/strings.h"
#include "asterisk/linkedlists.h"
#include "asterisk/utils.h"

Include dependency graph for localtime.c:

This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  lsinfo
 leap second information More...
struct  rule
struct  state

Defines

#define BIGGEST(a, b)   (((a) > (b)) ? (a) : (b))
#define DAY_OF_YEAR   1
#define JULIAN_DAY   0
#define MONTH_NTH_DAY_OF_WEEK   2
#define MY_TZNAME_MAX   255
#define OPEN_MODE   O_RDONLY
#define TZ_ABBR_CHAR_SET   "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 :+-._"
#define TZ_ABBR_ERR_CHAR   '_'
#define TZ_ABBR_MAX_LEN   16
#define TZ_STRLEN_MAX   255
#define TZDEFRULESTRING   ",M4.1.0,M10.5.0"
#define WRONG   (-1)

Functions

static char __attribute__ ((unused))
 time type information
static AST_LIST_HEAD_STATIC (zonelist, state)
tm * ast_localtime (const time_t *timep, struct tm *tmp, const char *zone)
time_t ast_mktime (struct tm *tmp, const char *zone)
static struct stateast_tzset (const char *zone)
static long detzcode (const char *const codep)
static time_t detzcode64 (const char *const codep)
static int differ_by_repeat (const time_t t1, const time_t t0)
static const char * getnum (const char *strp, int *nump, const int min, const int max)
 Given a pointer into a time zone string, extract a number from that string. Check that the number is within a specified range; if it is not, return NULL. Otherwise, return a pointer to the first character not part of the number.
static const char * getoffset (const char *strp, long *offsetp)
 Given a pointer into a time zone string, extract an offset, in [+-]hh[:mm[:ss]] form, from the string. If any error occurs, return NULL. Otherwise, return a pointer to the first character not part of the time.
static const char * getqzname (const char *strp, const int delim)
 Given a pointer into an extended time zone string, scan until the ending delimiter of the zone name is located. Return a pointer to the delimiter.
static const char * getrule (const char *strp, struct rule *rulep)
 Given a pointer into a time zone string, extract a rule in the form date[/time]. See POSIX section 8 for the format of "date" and "time". If a valid rule is not found, return NULL. Otherwise, return a pointer to the first character not part of the rule.
static const char * getsecs (const char *strp, long *const secsp)
 Given a pointer into a time zone string, extract a number of seconds, in hh[:mm[:ss]] form, from the string. If any error occurs, return NULL. Otherwise, return a pointer to the first character not part of the number of seconds.
static const char * getzname (const char *strp)
 Given a pointer into a time zone string, scan until a character that is not a valid character in a zone name is found. Return a pointer to that character.
static int gmtload (struct state *sp)
static struct tm * gmtsub (const time_t *timep, const long offset, struct tm *tmp)
static int increment_overflow (int *number, int delta)
 Simplified normalize logic courtesy Paul Eggert.
static int leaps_thru_end_of (const int y)
 Return the number of leap years through the end of the given year where, to make the math easy, the answer for year zero is defined as zero.
static struct tm * localsub (const time_t *timep, const long offset, struct tm *tmp, const struct state *sp)
static int long_increment_overflow (long *number, int delta)
static int long_normalize_overflow (long *tensptr, int *unitsptr, const int base)
static int normalize_overflow (int *tensptr, int *unitsptr, const int base)
static int tzparse P ((const char *name, struct state *sp, int lastditch))
static int tzload P ((const char *name, struct state *sp, int doextend))
static time_t transtime P ((time_t janfirst, int year, const struct rule *rulep, long offset))
static int tmcomp P ((const struct tm *atmp, const struct tm *btmp))
static struct tm *timesub P ((const time_t *timep, long offset, const struct state *sp, struct tm *tmp))
static time_t time2sub P ((struct tm *tmp, struct tm *(*funcp)(const time_t *, long, struct tm *, const struct state *sp), long offset, int *okayp, int do_norm_secs, const struct state *sp))
static time_t time2 P ((struct tm *tmp, struct tm *(*funcp) P((const time_t *, long, struct tm *, const struct state *sp)), long offset, int *okayp, const struct state *sp))
static time_t time1 P ((struct tm *tmp, struct tm *(*funcp) P((const time_t *, long, struct tm *, const struct state *sp)), long offset, const struct state *sp))
static int normalize_overflow P ((int *tensptr, int *unitsptr, const int base))
static int long_normalize_overflow P ((long *tensptr, int *unitsptr, const int base))
static int long_increment_overflow P ((long *number, int delta))
static int leaps_thru_end_of P ((int y))
static int increment_overflow P ((int *number, int delta))
static struct tm *localsub P ((const time_t *timep, long offset, struct tm *tmp, const struct state *sp))
static struct tm *gmtsub P ((const time_t *timep, long offset, struct tm *tmp))
static int gmtload P ((struct state *sp))
static const char *getrule P ((const char *strp, struct rule *rulep))
static const char *getoffset P ((const char *strp, long *offsetp))
static const char *getsecs P ((const char *strp, long *secsp))
static const char *getnum P ((const char *strp, int *nump, int min, int max))
static const char *getqzname P ((const char *strp, const int delim))
static const char *getzname P ((const char *strp))
static int differ_by_repeat P ((time_t t1, time_t t0))
static long detzcode P ((const char *codep))
static time_t time1 (struct tm *tmp, struct tm *(*const funcp)(const time_t *, long, struct tm *, const struct state *), const long offset, const struct state *sp)
static time_t time2 (struct tm *tmp, struct tm *(*const funcp)(const time_t *, long, struct tm *, const struct state *sp), const long offset, int *okayp, const struct state *sp)
static time_t time2sub (struct tm *tmp, struct tm *(*const funcp)(const time_t *, long, struct tm *, const struct state *), const long offset, int *okayp, const int do_norm_secs, const struct state *sp)
static struct tm * timesub (const time_t *timep, const long offset, const struct state *sp, struct tm *tmp)
static int tmcomp (const struct tm *atmp, const struct tm *btmp)
static time_t transtime (const time_t janfirst, const int year, const struct rule *rulep, const long offset)
 Given the Epoch-relative time of January 1, 00:00:00 UTC, in a year, the year, a rule, and the offset from UTC at the time that rule takes effect, calculate the Epoch-relative time that rule takes effect.
static int tzload (const char *name, struct state *const sp, const int doextend)
static int tzparse (const char *name, struct state *sp, const int lastditch)

Variables

static const int mon_lengths [2][MONSPERYEAR]
static const int year_lengths [2]


Detailed Description

Multi-timezone Localtime code

The original source from this file may be obtained from ftp://elsie.nci.nih.gov/pub/

Definition in file localtime.c.


Define Documentation

#define BIGGEST ( a,
 )     (((a) > (b)) ? (a) : (b))

Definition at line 130 of file localtime.c.

#define DAY_OF_YEAR   1

Definition at line 169 of file localtime.c.

Referenced by getrule(), and transtime().

#define JULIAN_DAY   0

Definition at line 168 of file localtime.c.

Referenced by getrule(), and transtime().

#define MONTH_NTH_DAY_OF_WEEK   2

Definition at line 170 of file localtime.c.

Referenced by getrule(), and transtime().

#define MY_TZNAME_MAX   255

Definition at line 136 of file localtime.c.

#define OPEN_MODE   O_RDONLY

Referenced by tzload().

#define TZ_ABBR_CHAR_SET   "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 :+-._"

#define TZ_ABBR_ERR_CHAR   '_'

#define TZ_ABBR_MAX_LEN   16

#define TZ_STRLEN_MAX   255

Definition at line 139 of file localtime.c.

#define TZDEFRULESTRING   ",M4.1.0,M10.5.0"

Referenced by tzparse().

#define WRONG   (-1)

Referenced by gmtload(), time1(), time2sub(), tzload(), and tzparse().


Function Documentation

static char __attribute__ ( (unused)   )  [static]

time type information

Note:
The DST rules to use if TZ has no rules and we can't load TZDEFRULES. We default to US rules as of 1999-08-17. POSIX 1003.1 section 8.1.1 says that the default DST rules are implementation dependent; for historical reasons, US rules are a common default.

Definition at line 70 of file localtime.c.

00080                                                                    :+-._"
00081 #endif /* !defined TZ_ABBR_CHAR_SET */
00082 
00083 #ifndef TZ_ABBR_ERR_CHAR
00084 #define TZ_ABBR_ERR_CHAR   '_'
00085 #endif /* !defined TZ_ABBR_ERR_CHAR */
00086 
00087 /*
00088 ** SunOS 4.1.1 headers lack O_BINARY.
00089 */
00090 
00091 #ifdef O_BINARY
00092 #define OPEN_MODE (O_RDONLY | O_BINARY)
00093 #endif /* defined O_BINARY */
00094 #ifndef O_BINARY
00095 #define OPEN_MODE O_RDONLY
00096 #endif /* !defined O_BINARY */
00097 
00098 static const char gmt[] = "GMT";
00099 
00100 /*! \note
00101  * The DST rules to use if TZ has no rules and we can't load TZDEFRULES.
00102  * We default to US rules as of 1999-08-17.
00103  * POSIX 1003.1 section 8.1.1 says that the default DST rules are
00104  * implementation dependent; for historical reasons, US rules are a
00105  * common default.
00106  */
00107 #ifndef TZDEFRULESTRING
00108 #define TZDEFRULESTRING ",M4.1.0,M10.5.0"
00109 #endif /* !defined TZDEFDST */
00110 
00111 #ifndef WRONG
00112 #define WRONG  (-1)
00113 #endif /* !defined WRONG */
00114 
00115 /*!< \brief time type information */
00116 struct ttinfo {            /* time type information */
00117    long     tt_gmtoff;  /* UTC offset in seconds */
00118    int      tt_isdst;   /* used to set tm_isdst */
00119    int      tt_abbrind; /* abbreviation list index */
00120    int      tt_ttisstd; /* TRUE if transition is std time */
00121    int      tt_ttisgmt; /* TRUE if transition is UTC */
00122 };

static AST_LIST_HEAD_STATIC ( zonelist  ,
state   
) [static]

struct tm* ast_localtime ( const time_t *  timep,
struct tm *  tmp,
const char *  zone 
)

Definition at line 1145 of file localtime.c.

References ast_tzset(), and localsub().

Referenced by acf_strftime(), append_date(), ast_check_timing(), ast_log(), ast_say_date_da(), ast_say_date_de(), ast_say_date_en(), ast_say_date_fr(), ast_say_date_ge(), ast_say_date_gr(), ast_say_date_nl(), ast_say_date_pt(), ast_say_date_with_format_da(), ast_say_date_with_format_de(), ast_say_date_with_format_en(), ast_say_date_with_format_es(), ast_say_date_with_format_fr(), ast_say_date_with_format_gr(), ast_say_date_with_format_he(), ast_say_date_with_format_it(), ast_say_date_with_format_nl(), ast_say_date_with_format_pl(), ast_say_date_with_format_pt(), ast_say_date_with_format_ru(), ast_say_date_with_format_tw(), ast_say_datetime_de(), ast_say_datetime_en(), ast_say_datetime_fr(), ast_say_datetime_from_now_en(), ast_say_datetime_from_now_fr(), ast_say_datetime_from_now_ge(), ast_say_datetime_from_now_pt(), ast_say_datetime_ge(), ast_say_datetime_gr(), ast_say_datetime_nl(), ast_say_datetime_pt(), ast_say_datetime_pt_BR(), ast_say_datetime_tw(), ast_say_time_de(), ast_say_time_en(), ast_say_time_fr(), ast_say_time_ge(), ast_say_time_gr(), ast_say_time_nl(), ast_say_time_pt(), ast_say_time_pt_BR(), ast_say_time_tw(), ast_verbose(), build_radius_record(), callerid_genmsg(), cdr_get_tv(), cli_prompt(), get_date(), iax2_datetime(), main(), manager_log(), mysql_log(), odbc_log(), pgsql_log(), phone_call(), play_message_datetime(), rpt_localtime(), say_date_generic(), sip_show_registry(), sqlite_log(), transmit_notify_request_with_callerid(), vmu_tm(), and write_metadata().

01146 {
01147    const struct state *sp = ast_tzset(zone);
01148    memset(tmp, 0, sizeof(*tmp));
01149    return sp ? localsub(timep, 0L, tmp, sp) : NULL;
01150 }

time_t ast_mktime ( struct tm *  tmp,
const char *  zone 
)

Definition at line 1643 of file localtime.c.

References ast_tzset(), localsub(), and time1().

Referenced by acf_strptime(), sms_readfile(), and unpackdate().

01644 {
01645    const struct state *sp;
01646    if (!(sp = ast_tzset(zone)))
01647       return 0;
01648    return time1(tmp, localsub, 0L, sp);
01649 }

static struct state* ast_tzset ( const char *  zone  )  [static]

Definition at line 1017 of file localtime.c.

References ast_calloc, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_strlen_zero(), FALSE, gmtload(), state::name, TRUE, tzload(), and tzparse().

Referenced by ast_localtime(), and ast_mktime().

01018 {
01019    struct state *sp;
01020 
01021    if (ast_strlen_zero(zone))
01022       zone = "/etc/localtime";
01023 
01024    AST_LIST_LOCK(&zonelist);
01025    AST_LIST_TRAVERSE(&zonelist, sp, list) {
01026       if (!strcmp(sp->name, zone)) {
01027          AST_LIST_UNLOCK(&zonelist);
01028          return sp;
01029       }
01030    }
01031    AST_LIST_UNLOCK(&zonelist);
01032 
01033    if (!(sp = ast_calloc(1, sizeof *sp)))
01034       return NULL;
01035 
01036    if (tzload(zone, sp, TRUE) != 0) {
01037       if (zone[0] == ':' || tzparse(zone, sp, FALSE) != 0)
01038          (void) gmtload(sp);
01039    }
01040    ast_copy_string(sp->name, zone, sizeof(sp->name));
01041    AST_LIST_LOCK(&zonelist);
01042    AST_LIST_INSERT_TAIL(&zonelist, sp, list);
01043    AST_LIST_UNLOCK(&zonelist);
01044    return sp;
01045 }

static long detzcode ( const char *const  codep  )  [static]

Note:
Section 4.12.3 of X3.159-1989 requires that Except for the strftime function, these functions [asctime, ctime, gmtime, localtime] return values in one of two static objects: a broken-down time structure and an array of char. Thanks to Paul Eggert for noting this.

Definition at line 235 of file localtime.c.

References result.

Referenced by tzload().

00236 {
00237    long  result;
00238    int   i;
00239 
00240    result = (codep[0] & 0x80) ? ~0L : 0;
00241    for (i = 0; i < 4; ++i)
00242       result = (result << 8) | (codep[i] & 0xff);
00243    return result;
00244 }

static time_t detzcode64 ( const char *const  codep  )  [static]

Definition at line 246 of file localtime.c.

References result.

Referenced by tzload().

00247 {
00248    time_t   result;
00249    int   i;
00250 
00251    result = (codep[0] & 0x80) ?  (~(int_fast64_t) 0) : 0;
00252    for (i = 0; i < 8; ++i)
00253       result = result * 256 + (codep[i] & 0xff);
00254    return result;
00255 }

static int differ_by_repeat ( const time_t  t1,
const time_t  t0 
) [static]

Definition at line 257 of file localtime.c.

References SECSPERREPEAT, SECSPERREPEAT_BITS, TYPE_BIT, TYPE_INTEGRAL, and TYPE_SIGNED.

00258 {
00259    const long long at1 = t1, at0 = t0;
00260    if (TYPE_INTEGRAL(time_t) &&
00261       TYPE_BIT(time_t) - TYPE_SIGNED(time_t) < SECSPERREPEAT_BITS)
00262          return 0;
00263    return at1 - at0 == SECSPERREPEAT;
00264 }

static const char* getnum ( const char *  strp,
int *  nump,
const int  min,
const int  max 
) [static]

Given a pointer into a time zone string, extract a number from that string. Check that the number is within a specified range; if it is not, return NULL. Otherwise, return a pointer to the first character not part of the number.

Definition at line 546 of file localtime.c.

References is_digit.

Referenced by getrule(), and getsecs().

00547 {
00548    char  c;
00549    int   num;
00550 
00551    if (strp == NULL || !is_digit(c = *strp))
00552       return NULL;
00553    num = 0;
00554    do {
00555       num = num * 10 + (c - '0');
00556       if (num > max)
00557          return NULL;   /* illegal value */
00558       c = *++strp;
00559    } while (is_digit(c));
00560    if (num < min)
00561       return NULL;      /* illegal value */
00562    *nump = num;
00563    return strp;
00564 }

static const char* getoffset ( const char *  strp,
long *  offsetp 
) [static]

Given a pointer into a time zone string, extract an offset, in [+-]hh[:mm[:ss]] form, from the string. If any error occurs, return NULL. Otherwise, return a pointer to the first character not part of the time.

Definition at line 613 of file localtime.c.

References getsecs().

Referenced by tzparse().

00614 {
00615    int   neg = 0;
00616 
00617    if (*strp == '-') {
00618       neg = 1;
00619       ++strp;
00620    } else if (*strp == '+')
00621       ++strp;
00622    strp = getsecs(strp, offsetp);
00623    if (strp == NULL)
00624       return NULL;      /* illegal time */
00625    if (neg)
00626       *offsetp = -*offsetp;
00627    return strp;
00628 }

static const char* getqzname ( const char *  strp,
const int  delim 
) [static]

Given a pointer into an extended time zone string, scan until the ending delimiter of the zone name is located. Return a pointer to the delimiter.

As with getzname above, the legal character set is actually quite restricted, with other characters producing undefined results. We don't do any checking here; checking is done later in common-case code.

Definition at line 530 of file localtime.c.

Referenced by tzparse().

00531 {
00532    int   c;
00533 
00534    while ((c = *strp) != '\0' && c != delim)
00535       ++strp;
00536    return strp;
00537 }

static const char* getrule ( const char *  strp,
struct rule rulep 
) [static]

Given a pointer into a time zone string, extract a rule in the form date[/time]. See POSIX section 8 for the format of "date" and "time". If a valid rule is not found, return NULL. Otherwise, return a pointer to the first character not part of the rule.

Definition at line 637 of file localtime.c.

References DAY_OF_YEAR, DAYSPERNYEAR, DAYSPERWEEK, getnum(), getsecs(), is_digit, JULIAN_DAY, MONSPERYEAR, MONTH_NTH_DAY_OF_WEEK, rule::r_day, rule::r_mon, rule::r_time, rule::r_type, rule::r_week, and SECSPERHOUR.

Referenced by tzparse().

00638 {
00639    if (*strp == 'J') {
00640       /*
00641       ** Julian day.
00642       */
00643       rulep->r_type = JULIAN_DAY;
00644       ++strp;
00645       strp = getnum(strp, &rulep->r_day, 1, DAYSPERNYEAR);
00646    } else if (*strp == 'M') {
00647       /*
00648       ** Month, week, day.
00649       */
00650       rulep->r_type = MONTH_NTH_DAY_OF_WEEK;
00651       ++strp;
00652       strp = getnum(strp, &rulep->r_mon, 1, MONSPERYEAR);
00653       if (strp == NULL)
00654          return NULL;
00655       if (*strp++ != '.')
00656          return NULL;
00657       strp = getnum(strp, &rulep->r_week, 1, 5);
00658       if (strp == NULL)
00659          return NULL;
00660       if (*strp++ != '.')
00661          return NULL;
00662       strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1);
00663    } else if (is_digit(*strp)) {
00664       /*
00665       ** Day of year.
00666       */
00667       rulep->r_type = DAY_OF_YEAR;
00668       strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1);
00669    } else   return NULL;      /* invalid format */
00670    if (strp == NULL)
00671       return NULL;
00672    if (*strp == '/') {
00673       /*
00674       ** Time specified.
00675       */
00676       ++strp;
00677       strp = getsecs(strp, &rulep->r_time);
00678    } else   rulep->r_time = 2 * SECSPERHOUR; /* default = 2:00:00 */
00679    return strp;
00680 }

static const char* getsecs ( const char *  strp,
long *const   secsp 
) [static]

Given a pointer into a time zone string, extract a number of seconds, in hh[:mm[:ss]] form, from the string. If any error occurs, return NULL. Otherwise, return a pointer to the first character not part of the number of seconds.

Definition at line 574 of file localtime.c.

References DAYSPERWEEK, getnum(), HOURSPERDAY, MINSPERHOUR, SECSPERHOUR, and SECSPERMIN.

Referenced by getoffset(), and getrule().

00575 {
00576    int   num;
00577 
00578    /*
00579    ** `HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like
00580    ** "M10.4.6/26", which does not conform to Posix,
00581    ** but which specifies the equivalent of
00582    ** ``02:00 on the first Sunday on or after 23 Oct''.
00583    */
00584    strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1);
00585    if (strp == NULL)
00586       return NULL;
00587    *secsp = num * (long) SECSPERHOUR;
00588    if (*strp == ':') {
00589       ++strp;
00590       strp = getnum(strp, &num, 0, MINSPERHOUR - 1);
00591       if (strp == NULL)
00592          return NULL;
00593       *secsp += num * SECSPERMIN;
00594       if (*strp == ':') {
00595          ++strp;
00596          /* `SECSPERMIN' allows for leap seconds. */
00597          strp = getnum(strp, &num, 0, SECSPERMIN);
00598          if (strp == NULL)
00599             return NULL;
00600          *secsp += num;
00601       }
00602    }
00603    return strp;
00604 }

static const char* getzname ( const char *  strp  )  [static]

Given a pointer into a time zone string, scan until a character that is not a valid character in a zone name is found. Return a pointer to that character.

Definition at line 511 of file localtime.c.

References is_digit.

Referenced by tzparse().

00512 {
00513    char  c;
00514 
00515    while ((c = *strp) != '\0' && !is_digit(c) && c != ',' && c != '-' &&
00516       c != '+')
00517          ++strp;
00518    return strp;
00519 }

static int gmtload ( struct state sp  )  [static]

Definition at line 1009 of file localtime.c.

References TRUE, tzload(), tzparse(), and WRONG.

Referenced by ast_tzset(), and gmtsub().

01010 {
01011    if (tzload(gmt, sp, TRUE) != 0)
01012       return tzparse(gmt, sp, TRUE);
01013    else
01014       return WRONG;
01015 }

static struct tm* gmtsub ( const time_t *  timep,
const long  offset,
struct tm *  tmp 
) [static]

Definition at line 1156 of file localtime.c.

References ast_calloc, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, state::chars, gmtload(), state::name, result, and timesub().

Referenced by localsub().

01157 {
01158    struct tm * result;
01159    struct state *sp;
01160 
01161    AST_LIST_LOCK(&zonelist);
01162    AST_LIST_TRAVERSE(&zonelist, sp, list) {
01163       if (!strcmp(sp->name, "UTC"))
01164          break;
01165    }
01166 
01167    if (!sp) {
01168       if (!(sp = (struct state *) ast_calloc(1, sizeof *sp)))
01169          return NULL;
01170       gmtload(sp);
01171       AST_LIST_INSERT_TAIL(&zonelist, sp, list);
01172    }
01173    AST_LIST_UNLOCK(&zonelist);
01174 
01175    result = timesub(timep, offset, sp, tmp);
01176 #ifdef TM_ZONE
01177    /*
01178    ** Could get fancy here and deliver something such as
01179    ** "UTC+xxxx" or "UTC-xxxx" if offset is non-zero,
01180    ** but this is no time for a treasure hunt.
01181    */
01182    if (offset != 0)
01183       tmp->TM_ZONE = "    ";
01184    else
01185       tmp->TM_ZONE = sp->chars;
01186 #endif /* defined TM_ZONE */
01187    return result;
01188 }

static int increment_overflow ( int *  number,
int  delta 
) [static]

Simplified normalize logic courtesy Paul Eggert.

Definition at line 1338 of file localtime.c.

Referenced by normalize_overflow(), and timesub().

01339 {
01340    int   number0;
01341 
01342    number0 = *number;
01343    *number += delta;
01344    return (*number < number0) != (delta < 0);
01345 }

static int leaps_thru_end_of ( const int  y  )  [static]

Return the number of leap years through the end of the given year where, to make the math easy, the answer for year zero is defined as zero.

Definition at line 1195 of file localtime.c.

Referenced by timesub().

01196 {
01197    return (y >= 0) ? (y / 4 - y / 100 + y / 400) :
01198       -(leaps_thru_end_of(-(y + 1)) + 1);
01199 }

static struct tm* localsub ( const time_t *  timep,
const long  offset,
struct tm *  tmp,
const struct state sp 
) [static]

Note:
The easy way to behave "as if no library function calls" localtime is to not call it--so we drop its guts into "localsub", which can be freely called. (And no, the PANS doesn't require the above behavior-- but it *is* desirable.)
The unused offset argument is for the benefit of mktime variants.

Definition at line 1056 of file localtime.c.

References state::ats, AVGSECSPERYEAR, state::chars, gmtsub(), state::goahead, state::goback, result, t, state::timecnt, timesub(), state::ttis, state::typecnt, state::types, and YEARSPERREPEAT.

Referenced by ast_localtime(), and ast_mktime().

01057 {
01058    const struct ttinfo *   ttisp;
01059    int         i;
01060    struct tm *    result;
01061    const time_t         t = *timep;
01062 
01063    if (sp == NULL)
01064       return gmtsub(timep, offset, tmp);
01065    if ((sp->goback && t < sp->ats[0]) ||
01066       (sp->goahead && t > sp->ats[sp->timecnt - 1])) {
01067          time_t         newt = t;
01068          time_t      seconds;
01069          time_t      tcycles;
01070          int_fast64_t   icycles;
01071 
01072          if (t < sp->ats[0])
01073             seconds = sp->ats[0] - t;
01074          else  seconds = t - sp->ats[sp->timecnt - 1];
01075          --seconds;
01076          tcycles = seconds / YEARSPERREPEAT / AVGSECSPERYEAR;
01077          ++tcycles;
01078          icycles = tcycles;
01079          if (tcycles - icycles >= 1 || icycles - tcycles >= 1)
01080             return NULL;
01081          seconds = icycles;
01082          seconds *= YEARSPERREPEAT;
01083          seconds *= AVGSECSPERYEAR;
01084          if (t < sp->ats[0])
01085             newt += seconds;
01086          else  newt -= seconds;
01087          if (newt < sp->ats[0] ||
01088             newt > sp->ats[sp->timecnt - 1])
01089                return NULL;   /* "cannot happen" */
01090          result = localsub(&newt, offset, tmp, sp);
01091          if (result == tmp) {
01092             time_t   newy;
01093 
01094             newy = tmp->tm_year;
01095             if (t < sp->ats[0])
01096                newy -= icycles * YEARSPERREPEAT;
01097             else
01098                newy += icycles * YEARSPERREPEAT;
01099             tmp->tm_year = newy;
01100             if (tmp->tm_year != newy)
01101                return NULL;
01102          }
01103          return result;
01104    }
01105    if (sp->timecnt == 0 || t < sp->ats[0]) {
01106       i = 0;
01107       while (sp->ttis[i].tt_isdst) {
01108          if (++i >= sp->typecnt) {
01109             i = 0;
01110             break;
01111          }
01112       }
01113    } else {
01114       int   lo = 1;
01115       int   hi = sp->timecnt;
01116 
01117       while (lo < hi) {
01118          int   mid = (lo + hi) >> 1;
01119 
01120          if (t < sp->ats[mid])
01121             hi = mid;
01122          else
01123             lo = mid + 1;
01124       }
01125       i = (int) sp->types[lo - 1];
01126    }
01127    ttisp = &sp->ttis[i];
01128    /*
01129    ** To get (wrong) behavior that's compatible with System V Release 2.0
01130    ** you'd replace the statement below with
01131    ** t += ttisp->tt_gmtoff;
01132    ** timesub(&t, 0L, sp, tmp);
01133    */
01134    result = timesub(&t, ttisp->tt_gmtoff, sp, tmp);
01135    tmp->tm_isdst = ttisp->tt_isdst;
01136 #ifndef SOLARIS /* Solaris doesn't have this element */
01137    tmp->tm_gmtoff = ttisp->tt_gmtoff;
01138 #endif
01139 #ifdef TM_ZONE
01140    tmp->TM_ZONE = &sp->chars[ttisp->tt_abbrind];
01141 #endif /* defined TM_ZONE */
01142    return result;
01143 }

static int long_increment_overflow ( long *  number,
int  delta 
) [static]

Definition at line 1347 of file localtime.c.

Referenced by long_normalize_overflow(), and time2sub().

01348 {
01349    long  number0;
01350 
01351    number0 = *number;
01352    *number += delta;
01353    return (*number < number0) != (delta < 0);
01354 }

static int long_normalize_overflow ( long *  tensptr,
int *  unitsptr,
const int  base 
) [static]

Definition at line 1367 of file localtime.c.

References long_increment_overflow().

Referenced by time2sub().

01368 {
01369    int   tensdelta;
01370 
01371    tensdelta = (*unitsptr >= 0) ?
01372       (*unitsptr / base) :
01373       (-1 - (-1 - *unitsptr) / base);
01374    *unitsptr -= tensdelta * base;
01375    return long_increment_overflow(tensptr, tensdelta);
01376 }

static int normalize_overflow ( int *  tensptr,
int *  unitsptr,
const int  base 
) [static]

Definition at line 1356 of file localtime.c.

References increment_overflow().

Referenced by time2sub().

01357 {
01358    int   tensdelta;
01359 
01360    tensdelta = (*unitsptr >= 0) ?
01361       (*unitsptr / base) :
01362       (-1 - (-1 - *unitsptr) / base);
01363    *unitsptr -= tensdelta * base;
01364    return increment_overflow(tensptr, tensdelta);
01365 }

static int tzparse P ( (const char *name, struct state *sp, int lastditch)   )  [static]

static int tzload P ( (const char *name, struct state *sp, int doextend)   )  [static]

static time_t transtime P ( (time_t janfirst, int year, const struct rule *rulep, long offset  )  [static]

static int tmcomp P ( (const struct tm *atmp, const struct tm *btmp)   )  [static]

static struct tm* timesub P ( (const time_t *timep, long offset, const struct state *sp, struct tm *tmp)   )  [static]

static time_t time2sub P ( (struct tm *tmp, struct tm *(*funcp)(const time_t *, long, struct tm *, const struct state *sp), long offset, int *okayp, int do_norm_secs, const struct state *sp)   )  [static]

static time_t time2 P ( (struct tm *tmp, struct tm *(*funcp) P((const time_t *, long, struct tm *, const struct state *sp)), long offset, int *okayp, const struct state *sp)   )  [static]

static time_t time1 P ( (struct tm *tmp, struct tm *(*funcp) P((const time_t *, long, struct tm *, const struct state *sp)), long offset, const struct state *sp)   )  [static]

static int normalize_overflow P ( (int *tensptr, int *unitsptr, const int base)   )  [static]

static int long_normalize_overflow P ( (long *tensptr, int *unitsptr, const int base)   )  [static]

static int long_increment_overflow P ( (long *number, int delta)   )  [static]

static int leaps_thru_end_of P ( (int y)   )  [static]

static int increment_overflow P ( (int *number, int delta)   )  [static]

static struct tm* localsub P ( (const time_t *timep, long offset, struct tm *tmp, const struct state *sp)   )  [static]

static struct tm* gmtsub P ( (const time_t *timep, long offset, struct tm *tmp)   )  [static]

static int gmtload P ( (struct state *sp)   )  [static]

static const char* getrule P ( (const char *strp, struct rule *rulep)   )  [static]

static const char* getoffset P ( (const char *strp, long *offsetp)   )  [static]

static const char* getsecs P ( (const char *strp, long *secsp)   )  [static]

static const char* getnum P ( (const char *strp, int *nump, int min, int max)   )  [static]

static const char* getqzname P ( (const char *strp, const int delim)   )  [static]

static const char* getzname P ( (const char *strp)   )  [static]

static int differ_by_repeat P ( (time_t t1, time_t t0)   )  [static]

static time_t detzcode64 P ( (const char *codep)   )  [static]

static time_t time1 ( struct tm *  tmp,
struct tm *(*)(const time_t *, long, struct tm *, const struct state *)  funcp,
const long  offset,
const struct state sp 
) [static]

Definition at line 1578 of file localtime.c.

References FALSE, time2(), state::timecnt, TRUE, state::typecnt, state::types, TZ_MAX_TYPES, and WRONG.

Referenced by ast_mktime().

01579 {
01580    time_t         t;
01581    int         samei, otheri;
01582    int         sameind, otherind;
01583    int         i;
01584    int         nseen;
01585    int            seen[TZ_MAX_TYPES];
01586    int            types[TZ_MAX_TYPES];
01587    int            okay;
01588 
01589    if (tmp->tm_isdst > 1)
01590       tmp->tm_isdst = 1;
01591    t = time2(tmp, funcp, offset, &okay, sp);
01592 #ifdef PCTS
01593    /*
01594    ** PCTS code courtesy Grant Sullivan.
01595    */
01596    if (okay)
01597       return t;
01598    if (tmp->tm_isdst < 0)
01599       tmp->tm_isdst = 0;   /* reset to std and try again */
01600 #endif /* defined PCTS */
01601 #ifndef PCTS
01602    if (okay || tmp->tm_isdst < 0)
01603       return t;
01604 #endif /* !defined PCTS */
01605    /*
01606    ** We're supposed to assume that somebody took a time of one type
01607    ** and did some math on it that yielded a "struct tm" that's bad.
01608    ** We try to divine the type they started from and adjust to the
01609    ** type they need.
01610    */
01611    if (sp == NULL)
01612       return WRONG;
01613    for (i = 0; i < sp->typecnt; ++i)
01614       seen[i] = FALSE;
01615    nseen = 0;
01616    for (i = sp->timecnt - 1; i >= 0; --i)
01617       if (!seen[sp->types[i]]) {
01618          seen[sp->types[i]] = TRUE;
01619          types[nseen++] = sp->types[i];
01620       }
01621    for (sameind = 0; sameind < nseen; ++sameind) {
01622       samei = types[sameind];
01623       if (sp->ttis[samei].tt_isdst != tmp->tm_isdst)
01624          continue;
01625       for (otherind = 0; otherind < nseen; ++otherind) {
01626          otheri = types[otherind];
01627          if (sp->ttis[otheri].tt_isdst == tmp->tm_isdst)
01628             continue;
01629          tmp->tm_sec += sp->ttis[otheri].tt_gmtoff -
01630                sp->ttis[samei].tt_gmtoff;
01631          tmp->tm_isdst = !tmp->tm_isdst;
01632          t = time2(tmp, funcp, offset, &okay, sp);
01633          if (okay)
01634             return t;
01635          tmp->tm_sec -= sp->ttis[otheri].tt_gmtoff -
01636                sp->ttis[samei].tt_gmtoff;
01637          tmp->tm_isdst = !tmp->tm_isdst;
01638       }
01639    }
01640    return WRONG;
01641 }

static time_t time2 ( struct tm *  tmp,
struct tm *(*)(const time_t *, long, struct tm *, const struct state *sp)  funcp,
const long  offset,
int *  okayp,
const struct state sp 
) [static]

Definition at line 1565 of file localtime.c.

References FALSE, time2sub(), and TRUE.

Referenced by time1().

01566 {
01567    time_t   t;
01568 
01569    /*! \note
01570    ** First try without normalization of seconds
01571    ** (in case tm_sec contains a value associated with a leap second).
01572    ** If that fails, try with normalization of seconds.
01573    */
01574    t = time2sub(tmp, funcp, offset, okayp, FALSE, sp);
01575    return *okayp ? t : time2sub(tmp, funcp, offset, okayp, TRUE, sp);
01576 }

static time_t time2sub ( struct tm *  tmp,
struct tm *(*)(const time_t *, long, struct tm *, const struct state *)  funcp,
const long  offset,
int *  okayp,
const int  do_norm_secs,
const struct state sp 
) [static]

Definition at line 1391 of file localtime.c.

References DAYSPERLYEAR, FALSE, HOURSPERDAY, isleap, long_increment_overflow(), long_normalize_overflow(), MINSPERHOUR, mon_lengths, MONSPERYEAR, normalize_overflow(), SECSPERMIN, t, TM_YEAR_BASE, WRONG, and year_lengths.

Referenced by time2().

01392 {
01393    int         dir;
01394    int         i, j;
01395    int         saved_seconds;
01396    long        li;
01397    time_t         lo;
01398    time_t         hi;
01399    long           y;
01400    time_t            newt;
01401    time_t            t;
01402    struct tm         yourtm, mytm;
01403 
01404    *okayp = FALSE;
01405    yourtm = *tmp;
01406    if (do_norm_secs) {
01407       if (normalize_overflow(&yourtm.tm_min, &yourtm.tm_sec,
01408          SECSPERMIN))
01409             return WRONG;
01410    }
01411    if (normalize_overflow(&yourtm.tm_hour, &yourtm.tm_min, MINSPERHOUR))
01412       return WRONG;
01413    if (normalize_overflow(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY))
01414       return WRONG;
01415    y = yourtm.tm_year;
01416    if (long_normalize_overflow(&y, &yourtm.tm_mon, MONSPERYEAR))
01417       return WRONG;
01418    /*
01419    ** Turn y into an actual year number for now.
01420    ** It is converted back to an offset from TM_YEAR_BASE later.
01421    */
01422    if (long_increment_overflow(&y, TM_YEAR_BASE))
01423       return WRONG;
01424    while (yourtm.tm_mday <= 0) {
01425       if (long_increment_overflow(&y, -1))
01426          return WRONG;
01427       li = y + (1 < yourtm.tm_mon);
01428       yourtm.tm_mday += year_lengths[isleap(li)];
01429    }
01430    while (yourtm.tm_mday > DAYSPERLYEAR) {
01431       li = y + (1 < yourtm.tm_mon);
01432       yourtm.tm_mday -= year_lengths[isleap(li)];
01433       if (long_increment_overflow(&y, 1))
01434          return WRONG;
01435    }
01436    for ( ; ; ) {
01437       i = mon_lengths[isleap(y)][yourtm.tm_mon];
01438       if (yourtm.tm_mday <= i)
01439          break;
01440       yourtm.tm_mday -= i;
01441       if (++yourtm.tm_mon >= MONSPERYEAR) {
01442          yourtm.tm_mon = 0;
01443          if (long_increment_overflow(&y, 1))
01444             return WRONG;
01445       }
01446    }
01447    if (long_increment_overflow(&y, -TM_YEAR_BASE))
01448       return WRONG;
01449    yourtm.tm_year = y;
01450    if (yourtm.tm_year != y)
01451       return WRONG;
01452    if (yourtm.tm_sec >= 0 && yourtm.tm_sec < SECSPERMIN)
01453       saved_seconds = 0;
01454    else if (y + TM_YEAR_BASE < EPOCH_YEAR) {
01455       /*
01456       ** We can't set tm_sec to 0, because that might push the
01457       ** time below the minimum representable time.
01458       ** Set tm_sec to 59 instead.
01459       ** This assumes that the minimum representable time is
01460       ** not in the same minute that a leap second was deleted from,
01461       ** which is a safer assumption than using 58 would be.
01462       */
01463       if (increment_overflow(&yourtm.tm_sec, 1 - SECSPERMIN))
01464          return WRONG;
01465       saved_seconds = yourtm.tm_sec;
01466       yourtm.tm_sec = SECSPERMIN - 1;
01467    } else {
01468       saved_seconds = yourtm.tm_sec;
01469       yourtm.tm_sec = 0;
01470    }
01471    /*
01472    ** Do a binary search (this works whatever time_t's type is).
01473    */
01474    if (!TYPE_SIGNED(time_t)) {
01475       lo = 0;
01476       hi = lo - 1;
01477    } else if (!TYPE_INTEGRAL(time_t)) {
01478       if (sizeof(time_t) > sizeof(float))
01479          hi = (time_t) DBL_MAX;
01480       else  hi = (time_t) FLT_MAX;
01481       lo = -hi;
01482    } else {
01483       lo = 1;
01484       for (i = 0; i < (int) TYPE_BIT(time_t) - 1; ++i)
01485          lo *= 2;
01486       hi = -(lo + 1);
01487    }
01488    for ( ; ; ) {
01489       t = lo / 2 + hi / 2;
01490       if (t < lo)
01491          t = lo;
01492       else if (t > hi)
01493          t = hi;
01494       if ((*funcp)(&t, offset, &mytm, sp) == NULL) {
01495          /*
01496          ** Assume that t is too extreme to be represented in
01497          ** a struct tm; arrange things so that it is less
01498          ** extreme on the next pass.
01499          */
01500          dir = (t > 0) ? 1 : -1;
01501       } else   dir = tmcomp(&mytm, &yourtm);
01502       if (dir != 0) {
01503          if (t == lo) {
01504             ++t;
01505             if (t <= lo)
01506                return WRONG;
01507             ++lo;
01508          } else if (t == hi) {
01509             --t;
01510             if (t >= hi)
01511                return WRONG;
01512             --hi;
01513          }
01514          if (lo > hi)
01515             return WRONG;
01516          if (dir > 0)
01517             hi = t;
01518          else  lo = t;
01519          continue;
01520       }
01521       if (yourtm.tm_isdst < 0 || mytm.tm_isdst == yourtm.tm_isdst)
01522          break;
01523       /*
01524       ** Right time, wrong type.
01525       ** Hunt for right time, right type.
01526       ** It's okay to guess wrong since the guess
01527       ** gets checked.
01528       */
01529       /*
01530       ** The (void *) casts are the benefit of SunOS 3.3 on Sun 2's.
01531       */
01532       for (i = sp->typecnt - 1; i >= 0; --i) {
01533          if (sp->ttis[i].tt_isdst != yourtm.tm_isdst)
01534             continue;
01535          for (j = sp->typecnt - 1; j >= 0; --j) {
01536             if (sp->ttis[j].tt_isdst == yourtm.tm_isdst)
01537                continue;
01538             newt = t + sp->ttis[j].tt_gmtoff -
01539                sp->ttis[i].tt_gmtoff;
01540             if ((*funcp)(&newt, offset, &mytm, sp) == NULL)
01541                continue;
01542             if (tmcomp(&mytm, &yourtm) != 0)
01543                continue;
01544             if (mytm.tm_isdst != yourtm.tm_isdst)
01545                continue;
01546             /*
01547             ** We have a match.
01548             */
01549             t = newt;
01550             goto label;
01551          }
01552       }
01553       return WRONG;
01554    }
01555 label:
01556    newt = t + saved_seconds;
01557    if ((newt < t) != (saved_seconds < 0))
01558       return WRONG;
01559    t = newt;
01560    if ((*funcp)(&t, offset, tmp, sp))
01561       *okayp = TRUE;
01562    return t;
01563 }

static struct tm* timesub ( const time_t *  timep,
const long  offset,
const struct state sp,
struct tm *  tmp 
) [static]

Definition at line 1201 of file localtime.c.

References DAYSPERLYEAR, DAYSPERNYEAR, DAYSPERWEEK, EPOCH_WDAY, EPOCH_YEAR, increment_overflow(), isleap, state::leapcnt, leaps_thru_end_of(), lsinfo::ls_corr, lsinfo::ls_trans, state::lsis, mon_lengths, SECSPERDAY, SECSPERHOUR, SECSPERMIN, TM_YEAR_BASE, and year_lengths.

Referenced by gmtsub(), and localsub().

01202 {
01203    const struct lsinfo *   lp;
01204    time_t         tdays;
01205    int         idays;   /* unsigned would be so 2003 */
01206    long        rem;
01207    int            y;
01208    const int *    ip;
01209    long        corr;
01210    int         hit;
01211    int         i;
01212    long  seconds;
01213 
01214 
01215    corr = 0;
01216    hit = 0;
01217    i = (sp == NULL) ? 0 : sp->leapcnt;
01218    while (--i >= 0) {
01219       lp = &sp->lsis[i];
01220       if (*timep >= lp->ls_trans) {
01221          if (*timep == lp->ls_trans) {
01222             hit = ((i == 0 && lp->ls_corr > 0) ||
01223                lp->ls_corr > sp->lsis[i - 1].ls_corr);
01224             if (hit)
01225                while (i > 0 &&
01226                   sp->lsis[i].ls_trans ==
01227                   sp->lsis[i - 1].ls_trans + 1 &&
01228                   sp->lsis[i].ls_corr ==
01229                   sp->lsis[i - 1].ls_corr + 1) {
01230                      ++hit;
01231                      --i;
01232                }
01233          }
01234          corr = lp->ls_corr;
01235          break;
01236       }
01237    }
01238    y = EPOCH_YEAR;
01239    tdays = *timep / SECSPERDAY;
01240    rem = *timep - tdays * SECSPERDAY;
01241    while (tdays < 0 || tdays >= year_lengths[isleap(y)]) {
01242       int      newy;
01243       time_t   tdelta;
01244       int   idelta;
01245       int   leapdays;
01246 
01247       tdelta = tdays / DAYSPERLYEAR;
01248       idelta = tdelta;
01249       if (tdelta - idelta >= 1 || idelta - tdelta >= 1)
01250          return NULL;
01251       if (idelta == 0)
01252          idelta = (tdays < 0) ? -1 : 1;
01253       newy = y;
01254       if (increment_overflow(&newy, idelta))
01255          return NULL;
01256       leapdays = leaps_thru_end_of(newy - 1) -
01257          leaps_thru_end_of(y - 1);
01258       tdays -= ((time_t) newy - y) * DAYSPERNYEAR;
01259       tdays -= leapdays;
01260       y = newy;
01261    }
01262 
01263    seconds = tdays * SECSPERDAY + 0.5;
01264    tdays = seconds / SECSPERDAY;
01265    rem += seconds - tdays * SECSPERDAY;
01266 
01267    /*
01268    ** Given the range, we can now fearlessly cast...
01269    */
01270    idays = tdays;
01271    rem += offset - corr;
01272    while (rem < 0) {
01273       rem += SECSPERDAY;
01274       --idays;
01275    }
01276    while (rem >= SECSPERDAY) {
01277       rem -= SECSPERDAY;
01278       ++idays;
01279    }
01280    while (idays < 0) {
01281       if (increment_overflow(&y, -1))
01282          return NULL;
01283       idays += year_lengths[isleap(y)];
01284    }
01285    while (idays >= year_lengths[isleap(y)]) {
01286       idays -= year_lengths[isleap(y)];
01287       if (increment_overflow(&y, 1))
01288          return NULL;
01289    }
01290    tmp->tm_year = y;
01291    if (increment_overflow(&tmp->tm_year, -TM_YEAR_BASE))
01292       return NULL;
01293    tmp->tm_yday = idays;
01294    /*
01295    ** The "extra" mods below avoid overflow problems.
01296    */
01297    tmp->tm_wday = EPOCH_WDAY +
01298       ((y - EPOCH_YEAR) % DAYSPERWEEK) *
01299       (DAYSPERNYEAR % DAYSPERWEEK) +
01300       leaps_thru_end_of(y - 1) -
01301       leaps_thru_end_of(EPOCH_YEAR - 1) +
01302       idays;
01303    tmp->tm_wday %= DAYSPERWEEK;
01304    if (tmp->tm_wday < 0)
01305       tmp->tm_wday += DAYSPERWEEK;
01306    tmp->tm_hour = (int) (rem / SECSPERHOUR);
01307    rem %= SECSPERHOUR;
01308    tmp->tm_min = (int) (rem / SECSPERMIN);
01309    /*
01310    ** A positive leap second requires a special
01311    ** representation. This uses "... ??:59:60" et seq.
01312    */
01313    tmp->tm_sec = (int) (rem % SECSPERMIN) + hit;
01314    ip = mon_lengths[isleap(y)];
01315    for (tmp->tm_mon = 0; idays >= ip[tmp->tm_mon]; ++(tmp->tm_mon))
01316       idays -= ip[tmp->tm_mon];
01317    tmp->tm_mday = (int) (idays + 1);
01318    tmp->tm_isdst = 0;
01319 #ifdef TM_GMTOFF
01320    tmp->TM_GMTOFF = offset;
01321 #endif /* defined TM_GMTOFF */
01322    return tmp;
01323 }

static int tmcomp ( const struct tm *  atmp,
const struct tm *  btmp 
) [static]

Definition at line 1378 of file localtime.c.

References result.

01379 {
01380    int   result;
01381 
01382    if ((result = (atmp->tm_year - btmp->tm_year)) == 0 &&
01383       (result = (atmp->tm_mon - btmp->tm_mon)) == 0 &&
01384       (result = (atmp->tm_mday - btmp->tm_mday)) == 0 &&
01385       (result = (atmp->tm_hour - btmp->tm_hour)) == 0 &&
01386       (result = (atmp->tm_min - btmp->tm_min)) == 0)
01387          result = atmp->tm_sec - btmp->tm_sec;
01388    return result;
01389 }

static time_t transtime ( const time_t  janfirst,
const int  year,
const struct rule rulep,
const long  offset 
) [static]

Given the Epoch-relative time of January 1, 00:00:00 UTC, in a year, the year, a rule, and the offset from UTC at the time that rule takes effect, calculate the Epoch-relative time that rule takes effect.

Definition at line 688 of file localtime.c.

References DAY_OF_YEAR, DAYSPERWEEK, INITIALIZE, isleap, JULIAN_DAY, m1, MONTH_NTH_DAY_OF_WEEK, rule::r_day, rule::r_mon, rule::r_time, rule::r_type, rule::r_week, and SECSPERDAY.

Referenced by tzparse().

00689 {
00690    int   leapyear;
00691    time_t   value;
00692    int   i;
00693    int      d, m1, yy0, yy1, yy2, dow;
00694 
00695    INITIALIZE(value);
00696    leapyear = isleap(year);
00697    switch (rulep->r_type) {
00698 
00699    case JULIAN_DAY:
00700       /*
00701       ** Jn - Julian day, 1 == January 1, 60 == March 1 even in leap
00702       ** years.
00703       ** In non-leap years, or if the day number is 59 or less, just
00704       ** add SECSPERDAY times the day number-1 to the time of
00705       ** January 1, midnight, to get the day.
00706       */
00707       value = janfirst + (rulep->r_day - 1) * SECSPERDAY;
00708       if (leapyear && rulep->r_day >= 60)
00709          value += SECSPERDAY;
00710       break;
00711 
00712    case DAY_OF_YEAR:
00713       /*
00714       ** n - day of year.
00715       ** Just add SECSPERDAY times the day number to the time of
00716       ** January 1, midnight, to get the day.
00717       */
00718       value = janfirst + rulep->r_day * SECSPERDAY;
00719       break;
00720 
00721    case MONTH_NTH_DAY_OF_WEEK:
00722       /*
00723       ** Mm.n.d - nth "dth day" of month m.
00724       */
00725       value = janfirst;
00726       for (i = 0; i < rulep->r_mon - 1; ++i)
00727          value += mon_lengths[leapyear][i] * SECSPERDAY;
00728 
00729       /*
00730       ** Use Zeller's Congruence to get day-of-week of first day of
00731       ** month.
00732       */
00733       m1 = (rulep->r_mon + 9) % 12 + 1;
00734       yy0 = (rulep->r_mon <= 2) ? (year - 1) : year;
00735       yy1 = yy0 / 100;
00736       yy2 = yy0 % 100;
00737       dow = ((26 * m1 - 2) / 10 +
00738          1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7;
00739       if (dow < 0)
00740          dow += DAYSPERWEEK;
00741 
00742       /*
00743       ** "dow" is the day-of-week of the first day of the month. Get
00744       ** the day-of-month (zero-origin) of the first "dow" day of the
00745       ** month.
00746       */
00747       d = rulep->r_day - dow;
00748       if (d < 0)
00749          d += DAYSPERWEEK;
00750       for (i = 1; i < rulep->r_week; ++i) {
00751          if (d + DAYSPERWEEK >=
00752             mon_lengths[leapyear][rulep->r_mon - 1])
00753                break;
00754          d += DAYSPERWEEK;
00755       }
00756 
00757       /*
00758       ** "d" is the day-of-month (zero-origin) of the day we want.
00759       */
00760       value += d * SECSPERDAY;
00761       break;
00762    }
00763 
00764    /*
00765    ** "value" is the Epoch-relative time of 00:00:00 UTC on the day in
00766    ** question. To get the Epoch-relative time of the specified local
00767    ** time on that day, add the transition time and the current offset
00768    ** from UTC.
00769    */
00770    return value + rulep->r_time + offset;
00771 }

static int tzload ( const char *  name,
struct state *const   sp,
const int  doextend 
) [static]

Definition at line 266 of file localtime.c.

References state::ats, state::charcnt, state::chars, detzcode(), detzcode64(), FALSE, FILENAME_MAX, state::leapcnt, lsinfo::ls_trans, state::lsis, OPEN_MODE, state::timecnt, TRUE, state::ttis, state::typecnt, state::types, TZ_MAX_CHARS, TZ_MAX_LEAPS, TZ_MAX_TIMES, TZ_MAX_TYPES, TZDEFAULT, TZDIR, and WRONG.

Referenced by ast_tzset(), gmtload(), and tzparse().

00267 {
00268    const char *      p;
00269    int         i;
00270    int         fid;
00271    int         stored;
00272    int         nread;
00273    union {
00274       struct tzhead  tzhead;
00275       char     buf[2 * sizeof(struct tzhead) +
00276                2 * sizeof *sp +
00277                4 * TZ_MAX_TIMES];
00278    } u;
00279 
00280    if (name == NULL && (name = TZDEFAULT) == NULL)
00281       return WRONG;
00282    {
00283       int   doaccess;
00284       /*
00285       ** Section 4.9.1 of the C standard says that
00286       ** "FILENAME_MAX expands to an integral constant expression
00287       ** that is the size needed for an array of char large enough
00288       ** to hold the longest file name string that the implementation
00289       ** guarantees can be opened."
00290       */
00291       char     fullname[FILENAME_MAX + 1];
00292 
00293       if (name[0] == ':')
00294          ++name;
00295       doaccess = name[0] == '/';
00296       if (!doaccess) {
00297          if ((p = TZDIR) == NULL)
00298             return WRONG;
00299          if ((strlen(p) + strlen(name) + 1) >= sizeof fullname)
00300             return WRONG;
00301          (void) strcpy(fullname, p);
00302          (void) strcat(fullname, "/");
00303          (void) strcat(fullname, name);
00304          /*
00305          ** Set doaccess if '.' (as in "../") shows up in name.
00306          */
00307          if (strchr(name, '.') != NULL)
00308             doaccess = TRUE;
00309          name = fullname;
00310       }
00311       if (doaccess && access(name, R_OK) != 0)
00312          return WRONG;
00313       if ((fid = open(name, OPEN_MODE)) == -1)
00314          return WRONG;
00315    }
00316    nread = read(fid, u.buf, sizeof u.buf);
00317    if (close(fid) < 0 || nread <= 0)
00318       return WRONG;
00319    for (stored = 4; stored <= 8; stored *= 2) {
00320       int      ttisstdcnt;
00321       int      ttisgmtcnt;
00322 
00323       ttisstdcnt = (int) detzcode(u.tzhead.tzh_ttisstdcnt);
00324       ttisgmtcnt = (int) detzcode(u.tzhead.tzh_ttisgmtcnt);
00325       sp->leapcnt = (int) detzcode(u.tzhead.tzh_leapcnt);
00326       sp->timecnt = (int) detzcode(u.tzhead.tzh_timecnt);
00327       sp->typecnt = (int) detzcode(u.tzhead.tzh_typecnt);
00328       sp->charcnt = (int) detzcode(u.tzhead.tzh_charcnt);
00329       p = u.tzhead.tzh_charcnt + sizeof u.tzhead.tzh_charcnt;
00330       if (sp->leapcnt < 0 || sp->leapcnt > TZ_MAX_LEAPS ||
00331          sp->typecnt <= 0 || sp->typecnt > TZ_MAX_TYPES ||
00332          sp->timecnt < 0 || sp->timecnt > TZ_MAX_TIMES ||
00333          sp->charcnt < 0 || sp->charcnt > TZ_MAX_CHARS ||
00334          (ttisstdcnt != sp->typecnt && ttisstdcnt != 0) ||
00335          (ttisgmtcnt != sp->typecnt && ttisgmtcnt != 0))
00336             return WRONG;
00337       if (nread - (p - u.buf) <
00338          sp->timecnt * stored +     /* ats */
00339          sp->timecnt +        /* types */
00340          sp->typecnt * 6 +    /* ttinfos */
00341          sp->charcnt +        /* chars */
00342          sp->leapcnt * (stored + 4) +  /* lsinfos */
00343          ttisstdcnt +         /* ttisstds */
00344          ttisgmtcnt)       /* ttisgmts */
00345             return WRONG;
00346       for (i = 0; i < sp->timecnt; ++i) {
00347          sp->ats[i] = (stored == 4) ?
00348             detzcode(p) : detzcode64(p);
00349          p += stored;
00350       }
00351       for (i = 0; i < sp->timecnt; ++i) {
00352          sp->types[i] = (unsigned char) *p++;
00353          if (sp->types[i] >= sp->typecnt)
00354             return WRONG;
00355       }
00356       for (i = 0; i < sp->typecnt; ++i) {
00357          struct ttinfo *   ttisp;
00358 
00359          ttisp = &sp->ttis[i];
00360          ttisp->tt_gmtoff = detzcode(p);
00361          p += 4;
00362          ttisp->tt_isdst = (unsigned char) *p++;
00363          if (ttisp->tt_isdst != 0 && ttisp->tt_isdst != 1)
00364             return WRONG;
00365          ttisp->tt_abbrind = (unsigned char) *p++;
00366          if (ttisp->tt_abbrind < 0 ||
00367             ttisp->tt_abbrind > sp->charcnt)
00368                return WRONG;
00369       }
00370       for (i = 0; i < sp->charcnt; ++i)
00371          sp->chars[i] = *p++;
00372       sp->chars[i] = '\0'; /* ensure '\0' at end */
00373       for (i = 0; i < sp->leapcnt; ++i) {
00374          struct lsinfo *   lsisp;
00375 
00376          lsisp = &sp->lsis[i];
00377          lsisp->ls_trans = (stored == 4) ?
00378             detzcode(p) : detzcode64(p);
00379          p += stored;
00380          lsisp->ls_corr = detzcode(p);
00381          p += 4;
00382       }
00383       for (i = 0; i < sp->typecnt; ++i) {
00384          struct ttinfo *   ttisp;
00385 
00386          ttisp = &sp->ttis[i];
00387          if (ttisstdcnt == 0)
00388             ttisp->tt_ttisstd = FALSE;
00389          else {
00390             ttisp->tt_ttisstd = *p++;
00391             if (ttisp->tt_ttisstd != TRUE &&
00392                ttisp->tt_ttisstd != FALSE)
00393                   return WRONG;
00394          }
00395       }
00396       for (i = 0; i < sp->typecnt; ++i) {
00397          struct ttinfo *   ttisp;
00398 
00399          ttisp = &sp->ttis[i];
00400          if (ttisgmtcnt == 0)
00401             ttisp->tt_ttisgmt = FALSE;
00402          else {
00403             ttisp->tt_ttisgmt = *p++;
00404             if (ttisp->tt_ttisgmt != TRUE &&
00405                ttisp->tt_ttisgmt != FALSE)
00406                   return WRONG;
00407          }
00408       }
00409       /*
00410       ** Out-of-sort ats should mean we're running on a
00411       ** signed time_t system but using a data file with
00412       ** unsigned values (or vice versa).
00413       */
00414       for (i = 0; i < sp->timecnt - 2; ++i)
00415          if (sp->ats[i] > sp->ats[i + 1]) {
00416             ++i;
00417             if (TYPE_SIGNED(time_t)) {
00418                /*
00419                ** Ignore the end (easy).
00420                */
00421                sp->timecnt = i;
00422             } else {
00423                /*
00424                ** Ignore the beginning (harder).
00425                */
00426                int   j;
00427 
00428                for (j = 0; j + i < sp->timecnt; ++j) {
00429                   sp->ats[j] = sp->ats[j + i];
00430                   sp->types[j] = sp->types[j + i];
00431                }
00432                sp->timecnt = j;
00433             }
00434             break;
00435          }
00436       /*
00437       ** If this is an old file, we're done.
00438       */
00439       if (u.tzhead.tzh_version[0] == '\0')
00440          break;
00441       nread -= p - u.buf;
00442       for (i = 0; i < nread; ++i)
00443          u.buf[i] = p[i];
00444       /*
00445       ** If this is a narrow integer time_t system, we're done.
00446       */
00447       if (stored >= (int) sizeof(time_t) && TYPE_INTEGRAL(time_t))
00448          break;
00449    }
00450    if (doextend && nread > 2 &&
00451       u.buf[0] == '\n' && u.buf[nread - 1] == '\n' &&
00452       sp->typecnt + 2 <= TZ_MAX_TYPES) {
00453          struct state   ts;
00454          int   result;
00455 
00456          u.buf[nread - 1] = '\0';
00457          result = tzparse(&u.buf[1], &ts, FALSE);
00458          if (result == 0 && ts.typecnt == 2 &&
00459             sp->charcnt + ts.charcnt <= TZ_MAX_CHARS) {
00460                for (i = 0; i < 2; ++i)
00461                   ts.ttis[i].tt_abbrind +=
00462                      sp->charcnt;
00463                for (i = 0; i < ts.charcnt; ++i)
00464                   sp->chars[sp->charcnt++] =
00465                      ts.chars[i];
00466                i = 0;
00467                while (i < ts.timecnt &&
00468                   ts.ats[i] <=
00469                   sp->ats[sp->timecnt - 1])
00470                      ++i;
00471                while (i < ts.timecnt &&
00472                    sp->timecnt < TZ_MAX_TIMES) {
00473                   sp->ats[sp->timecnt] =
00474                      ts.ats[i];
00475                   sp->types[sp->timecnt] =
00476                      sp->typecnt +
00477                      ts.types[i];
00478                   ++sp->timecnt;
00479                   ++i;
00480                }
00481                sp->ttis[sp->typecnt++] = ts.ttis[0];
00482                sp->ttis[sp->typecnt++] = ts.ttis[1];
00483          }
00484    }
00485    i = 2 * YEARSPERREPEAT;
00486    sp->goback = sp->goahead = sp->timecnt > i;
00487    sp->goback = sp->goback && sp->types[i] == sp->types[0] &&
00488       differ_by_repeat(sp->ats[i], sp->ats[0]);
00489    sp->goahead = sp->goahead &&
00490       sp->types[sp->timecnt - 1] == sp->types[sp->timecnt - 1 - i] &&
00491       differ_by_repeat(sp->ats[sp->timecnt - 1],
00492           sp->ats[sp->timecnt - 1 - i]);
00493    return 0;
00494 }

static int tzparse ( const char *  name,
struct state sp,
const int  lastditch 
) [static]

Note:
Given a POSIX section 8-style TZ string, fill in the rule tables as appropriate.

Definition at line 778 of file localtime.c.

References state::ats, state::chars, EPOCH_YEAR, FALSE, getoffset(), getqzname(), getrule(), getzname(), INITIALIZE, isleap, state::leapcnt, SECSPERDAY, SECSPERHOUR, starttime, state::timecnt, transtime(), state::ttis, state::typecnt, state::types, TZ_MAX_TIMES, TZDEFRULES, TZDEFRULESTRING, tzload(), and WRONG.

Referenced by ast_tzset(), and gmtload().

00779 {
00780    const char *         stdname;
00781    const char *         dstname;
00782    size_t            stdlen;
00783    size_t            dstlen;
00784    long           stdoffset;
00785    long           dstoffset;
00786    time_t *    atp;
00787    unsigned char *   typep;
00788    char *         cp;
00789    int         load_result;
00790 
00791    INITIALIZE(dstname);
00792    stdname = name;
00793    if (lastditch) {
00794       stdlen = strlen(name);  /* length of standard zone name */
00795       name += stdlen;
00796       if (stdlen >= sizeof sp->chars)
00797          stdlen = (sizeof sp->chars) - 1;
00798       stdoffset = 0;
00799    } else {
00800       if (*name == '<') {
00801          name++;
00802          stdname = name;
00803          name = getqzname(name, '>');
00804          if (*name != '>')
00805             return WRONG;
00806          stdlen = name - stdname;
00807          name++;
00808       } else {
00809          name = getzname(name);
00810          stdlen = name - stdname;
00811       }
00812       if (*name == '\0')
00813          return WRONG;
00814       name = getoffset(name, &stdoffset);
00815       if (name == NULL)
00816          return WRONG;
00817    }
00818    load_result = tzload(TZDEFRULES, sp, FALSE);
00819    if (load_result != 0)
00820       sp->leapcnt = 0;     /* so, we're off a little */
00821    if (*name != '\0') {
00822       if (*name == '<') {
00823          dstname = ++name;
00824          name = getqzname(name, '>');
00825          if (*name != '>')
00826             return WRONG;
00827          dstlen = name - dstname;
00828          name++;
00829       } else {
00830          dstname = name;
00831          name = getzname(name);
00832          dstlen = name - dstname; /* length of DST zone name */
00833       }
00834       if (*name != '\0' && *name != ',' && *name != ';') {
00835          name = getoffset(name, &dstoffset);
00836          if (name == NULL)
00837             return WRONG;
00838       } else   dstoffset = stdoffset - SECSPERHOUR;
00839       if (*name == '\0' && load_result != 0)
00840          name = TZDEFRULESTRING;
00841       if (*name == ',' || *name == ';') {
00842          struct rule start;
00843          struct rule end;
00844          int   year;
00845          time_t   janfirst;
00846          time_t      starttime;
00847          time_t      endtime;
00848 
00849          ++name;
00850          if ((name = getrule(name, &start)) == NULL)
00851             return WRONG;
00852          if (*name++ != ',')
00853             return WRONG;
00854          if ((name = getrule(name, &end)) == NULL)
00855             return WRONG;
00856          if (*name != '\0')
00857             return WRONG;
00858          sp->typecnt = 2;  /* standard time and DST */
00859          /*
00860          ** Two transitions per year, from EPOCH_YEAR forward.
00861          */
00862          sp->ttis[0].tt_gmtoff = -dstoffset;
00863          sp->ttis[0].tt_isdst = 1;
00864          sp->ttis[0].tt_abbrind = stdlen + 1;
00865          sp->ttis[1].tt_gmtoff = -stdoffset;
00866          sp->ttis[1].tt_isdst = 0;
00867          sp->ttis[1].tt_abbrind = 0;
00868          atp = sp->ats;
00869          typep = sp->types;
00870          janfirst = 0;
00871          sp->timecnt = 0;
00872          for (year = EPOCH_YEAR;
00873              sp->timecnt + 2 <= TZ_MAX_TIMES;
00874              ++year) {
00875                time_t   newfirst;
00876 
00877             starttime = transtime(janfirst, year, &start,
00878                stdoffset);
00879             endtime = transtime(janfirst, year, &end,
00880                dstoffset);
00881             if (starttime > endtime) {
00882                *atp++ = endtime;
00883                *typep++ = 1;  /* DST ends */
00884                *atp++ = starttime;
00885                *typep++ = 0;  /* DST begins */
00886             } else {
00887                *atp++ = starttime;
00888                *typep++ = 0;  /* DST begins */
00889                *atp++ = endtime;
00890                *typep++ = 1;  /* DST ends */
00891             }
00892             sp->timecnt += 2;
00893             newfirst = janfirst;
00894             newfirst += year_lengths[isleap(year)] *
00895                SECSPERDAY;
00896             if (newfirst <= janfirst)
00897                break;
00898             janfirst = newfirst;
00899          }
00900       } else {
00901          long  theirstdoffset;
00902          long  theirdstoffset;
00903          long  theiroffset;
00904          int   isdst;
00905          int   i;
00906          int   j;
00907 
00908          if (*name != '\0')
00909             return WRONG;
00910          /*
00911          ** Initial values of theirstdoffset and theirdstoffset.
00912          */
00913          theirstdoffset = 0;
00914          for (i = 0; i < sp->timecnt; ++i) {
00915             j = sp->types[i];
00916             if (!sp->ttis[j].tt_isdst) {
00917                theirstdoffset =
00918                   -sp->ttis[j].tt_gmtoff;
00919                break;
00920             }
00921          }
00922          theirdstoffset = 0;
00923          for (i = 0; i < sp->timecnt; ++i) {
00924             j = sp->types[i];
00925             if (sp->ttis[j].tt_isdst) {
00926                theirdstoffset =
00927                   -sp->ttis[j].tt_gmtoff;
00928                break;
00929             }
00930          }
00931          /*
00932          ** Initially we're assumed to be in standard time.
00933          */
00934          isdst = FALSE;
00935          theiroffset = theirstdoffset;
00936          /*
00937          ** Now juggle transition times and types
00938          ** tracking offsets as you do.
00939          */
00940          for (i = 0; i < sp->timecnt; ++i) {
00941             j = sp->types[i];
00942             sp->types[i] = sp->ttis[j].tt_isdst;
00943             if (sp->ttis[j].tt_ttisgmt) {
00944                /* No adjustment to transition time */
00945             } else {
00946                /*
00947                ** If summer time is in effect, and the
00948                ** transition time was not specified as
00949                ** standard time, add the summer time
00950                ** offset to the transition time;
00951                ** otherwise, add the standard time
00952                ** offset to the transition time.
00953                */
00954                /*
00955                ** Transitions from DST to DDST
00956                ** will effectively disappear since
00957                ** POSIX provides for only one DST
00958                ** offset.
00959                */
00960                if (isdst && !sp->ttis[j].tt_ttisstd) {
00961                   sp->ats[i] += dstoffset -
00962                      theirdstoffset;
00963                } else {
00964                   sp->ats[i] += stdoffset -
00965                      theirstdoffset;
00966                }
00967             }
00968             theiroffset = -sp->ttis[j].tt_gmtoff;
00969             if (sp->ttis[j].tt_isdst)
00970                theirdstoffset = theiroffset;
00971             else  theirstdoffset = theiroffset;
00972          }
00973          /*
00974          ** Finally, fill in ttis.
00975          ** ttisstd and ttisgmt need not be handled.
00976          */
00977          sp->ttis[0].tt_gmtoff = -stdoffset;
00978          sp->ttis[0].tt_isdst = FALSE;
00979          sp->ttis[0].tt_abbrind = 0;
00980          sp->ttis[1].tt_gmtoff = -dstoffset;
00981          sp->ttis[1].tt_isdst = TRUE;
00982          sp->ttis[1].tt_abbrind = stdlen + 1;
00983          sp->typecnt = 2;
00984       }
00985    } else {
00986       dstlen = 0;
00987       sp->typecnt = 1;     /* only standard time */
00988       sp->timecnt = 0;
00989       sp->ttis[0].tt_gmtoff = -stdoffset;
00990       sp->ttis[0].tt_isdst = 0;
00991       sp->ttis[0].tt_abbrind = 0;
00992    }
00993    sp->charcnt = stdlen + 1;
00994    if (dstlen != 0)
00995       sp->charcnt += dstlen + 1;
00996    if ((size_t) sp->charcnt > sizeof sp->chars)
00997       return WRONG;
00998    cp = sp->chars;
00999    (void) strncpy(cp, stdname, stdlen);
01000    cp += stdlen;
01001    *cp++ = '\0';
01002    if (dstlen != 0) {
01003       (void) strncpy(cp, dstname, dstlen);
01004       *(cp + dstlen) = '\0';
01005    }
01006    return 0;
01007 }


Variable Documentation

const int mon_lengths[2][MONSPERYEAR] [static]

Initial value:

 {
   { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
   { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
}

Definition at line 496 of file localtime.c.

Referenced by time2sub(), and timesub().

const int year_lengths[2] [static]

Initial value:

Definition at line 501 of file localtime.c.

Referenced by time2sub(), and timesub().


Generated on Mon Mar 31 07:41:16 2008 for Asterisk - the Open Source PBX by  doxygen 1.5.1