Sat Aug 6 00:39:58 2011

Asterisk developer's documentation


localtime.c File Reference

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

Go to the source code of this file.

Data Structures

struct  lsinfo
 leap second information More...
struct  rule
struct  state
struct  ttinfo
 time type information More...
struct  zonelist

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

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 char elsieid [] = "@(#)localtime.c 8.5"
static const char gmt [] = "GMT"
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 131 of file localtime.c.

#define DAY_OF_YEAR   1

Definition at line 170 of file localtime.c.

Referenced by getrule(), and transtime().

#define JULIAN_DAY   0

Definition at line 169 of file localtime.c.

Referenced by getrule(), and transtime().

#define MONTH_NTH_DAY_OF_WEEK   2

Definition at line 171 of file localtime.c.

Referenced by getrule(), and transtime().

#define MY_TZNAME_MAX   255

Definition at line 137 of file localtime.c.

#define OPEN_MODE   O_RDONLY

Definition at line 96 of file localtime.c.

Referenced by tzload().

#define TZ_ABBR_CHAR_SET   "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 :+-._"

Definition at line 80 of file localtime.c.

#define TZ_ABBR_ERR_CHAR   '_'

Definition at line 85 of file localtime.c.

#define TZ_ABBR_MAX_LEN   16

Definition at line 76 of file localtime.c.

#define TZ_STRLEN_MAX   255

Definition at line 140 of file localtime.c.

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

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 109 of file localtime.c.

Referenced by tzparse().

#define WRONG   (-1)

Definition at line 113 of file localtime.c.

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


Function Documentation

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

Definition at line 1146 of file localtime.c.

References ast_tzset(), and localsub().

Referenced by acf_strftime(), action_corestatus(), append_date(), ast_check_timing(), ast_log(), ast_say_date_da(), ast_say_date_de(), ast_say_date_en(), ast_say_date_es(), ast_say_date_fr(), ast_say_date_gr(), ast_say_date_he(), ast_say_date_ka(), 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_zh(), 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_he(), ast_say_datetime_from_now_ka(), ast_say_datetime_from_now_pt(), ast_say_datetime_gr(), ast_say_datetime_he(), ast_say_datetime_ka(), ast_say_datetime_nl(), ast_say_datetime_pt(), ast_say_datetime_pt_BR(), ast_say_datetime_zh(), ast_say_time_de(), ast_say_time_en(), ast_say_time_es(), ast_say_time_fr(), ast_say_time_gr(), ast_say_time_he(), ast_say_time_ka(), ast_say_time_nl(), ast_say_time_pt(), ast_say_time_pt_BR(), ast_say_time_zh(), ast_verbose(), build_query(), build_radius_record(), callerid_genmsg(), cdr_get_tv(), cli_prompt(), get_date(), handle_show_settings(), iax2_datetime(), main(), make_email_file(), manager_log(), pgsql_log(), phone_call(), play_message_datetime(), prep_email_sub_vars(), rpt_localtime(), say_date_generic(), sip_show_registry(), sqlite_log(), transmit_notify_request_with_callerid(), vmu_tm(), and write_metadata().

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

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

Definition at line 1644 of file localtime.c.

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

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

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

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

Definition at line 1018 of file localtime.c.

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

Referenced by ast_localtime(), and ast_mktime().

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

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 236 of file localtime.c.

Referenced by tzload().

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

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

Definition at line 247 of file localtime.c.

Referenced by tzload().

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

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

Definition at line 258 of file localtime.c.

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

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

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 547 of file localtime.c.

References is_digit.

Referenced by getrule(), and getsecs().

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

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 614 of file localtime.c.

References getsecs().

Referenced by tzparse().

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

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 531 of file localtime.c.

Referenced by tzparse().

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

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 638 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().

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

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 575 of file localtime.c.

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

Referenced by getoffset(), and getrule().

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

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 512 of file localtime.c.

References is_digit.

Referenced by tzparse().

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

static int gmtload ( struct state sp  )  [static]

Definition at line 1010 of file localtime.c.

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

Referenced by ast_tzset(), and gmtsub().

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

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

Definition at line 1157 of file localtime.c.

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

Referenced by localsub().

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

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

Simplified normalize logic courtesy Paul Eggert.

Definition at line 1339 of file localtime.c.

Referenced by normalize_overflow(), and timesub().

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

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 1196 of file localtime.c.

Referenced by timesub().

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

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 1057 of file localtime.c.

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

Referenced by ast_localtime(), and ast_mktime().

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

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

Definition at line 1348 of file localtime.c.

Referenced by long_normalize_overflow(), and time2sub().

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

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

Definition at line 1368 of file localtime.c.

References long_increment_overflow().

Referenced by time2sub().

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

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

Definition at line 1357 of file localtime.c.

References increment_overflow().

Referenced by time2sub().

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

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 1579 of file localtime.c.

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

Referenced by ast_mktime().

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

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 1566 of file localtime.c.

References FALSE, time2sub(), and TRUE.

Referenced by time1().

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

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 1392 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().

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

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

Definition at line 1202 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().

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

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

Definition at line 1379 of file localtime.c.

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

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 689 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().

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

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

Definition at line 267 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, ttinfo::tt_gmtoff, ttinfo::tt_ttisgmt, ttinfo::tt_ttisstd, 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().

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

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 779 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(), ttinfo::tt_abbrind, ttinfo::tt_gmtoff, ttinfo::tt_isdst, ttinfo::tt_ttisgmt, ttinfo::tt_ttisstd, state::ttis, state::typecnt, state::types, TZ_MAX_TIMES, TZDEFRULES, TZDEFRULESTRING, tzload(), and WRONG.

Referenced by ast_tzset(), and gmtload().

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


Variable Documentation

char elsieid[] = "@(#)localtime.c 8.5" [static]

Definition at line 71 of file localtime.c.

const char gmt[] = "GMT" [static]

Definition at line 99 of file localtime.c.

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 497 of file localtime.c.

Referenced by time2sub(), and timesub().

const int year_lengths[2] [static]

Initial value:

Definition at line 502 of file localtime.c.

Referenced by time2sub(), and timesub().


Generated on Sat Aug 6 00:39:58 2011 for Asterisk - the Open Source PBX by  doxygen 1.4.7