Sat Nov 1 06:29:09 2008

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"

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 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

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

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

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 1146 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_he(), 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_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_he(), ast_say_datetime_from_now_pt(), ast_say_datetime_ge(), ast_say_datetime_gr(), ast_say_datetime_he(), 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_he(), ast_say_time_nl(), ast_say_time_pt(), ast_say_time_pt_BR(), ast_say_time_tw(), ast_verbose(), build_query(), build_radius_record(), callerid_genmsg(), cdr_get_tv(), cli_prompt(), get_date(), iax2_datetime(), main(), manager_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().

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

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.

References int_fast64_t.

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::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, int_fast64_t, t, state::timecnt, timesub(), 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]