Wed Oct 28 11:52:48 2009

Asterisk developer's documentation


localtime.c File Reference

#include "asterisk.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
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"

Functions

void ast_get_dst_info (const time_t *const timep, int *dst_enabled, time_t *dst_start, time_t *dst_end, int *gmt_off, const char *const zone)
struct ast_tmast_localtime (const struct timeval *timep, struct ast_tm *tmp, const char *zone)
struct timeval ast_mktime (struct ast_tm *tmp, const char *zone)
int ast_strftime (char *buf, size_t len, const char *tmp, const struct ast_tm *tm)
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 ast_tmgmtsub (const struct timeval *timep, const long offset, struct ast_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 ast_tmlocalsub (const struct timeval *timep, const long offset, struct ast_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 ast_tm *atmp, const struct ast_tm *btmp))
static struct ast_tm *timesub P ((const struct timeval *timep, long offset, const struct state *sp, struct ast_tm *tmp))
static struct timeval time2sub P ((struct ast_tm *tmp, struct ast_tm *(*funcp)(const struct timeval *, long, struct ast_tm *, const struct state *sp), long offset, int *okayp, int do_norm_secs, const struct state *sp))
static struct timeval time2 P ((struct ast_tm *tmp, struct ast_tm *(*funcp) P((const struct timeval *, long, struct ast_tm *, const struct state *sp)), long offset, int *okayp, const struct state *sp))
static struct timeval time1 P ((struct ast_tm *tmp, struct ast_tm *(*funcp) P((const struct timeval *, long, struct ast_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 ast_tm *localsub P ((const struct timeval *timep, long offset, struct ast_tm *tmp, const struct state *sp))
static struct ast_tm *gmtsub P ((const struct timeval *timep, long offset, struct ast_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 struct timeval time1 (struct ast_tm *tmp, struct ast_tm *(*const funcp)(const struct timeval *, long, struct ast_tm *, const struct state *), const long offset, const struct state *sp)
static struct timeval time2 (struct ast_tm *tmp, struct ast_tm *(*const funcp)(const struct timeval *, long, struct ast_tm *, const struct state *sp), const long offset, int *okayp, const struct state *sp)
static struct timeval time2sub (struct ast_tm *tmp, struct ast_tm *(*const funcp)(const struct timeval *, long, struct ast_tm *, const struct state *), const long offset, int *okayp, const int do_norm_secs, const struct state *sp)
static struct ast_tmtimesub (const struct timeval *timep, const long offset, const struct state *sp, struct ast_tm *tmp)
static int tmcomp (const struct ast_tm *atmp, const struct ast_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 struct timeval WRONG = { 0, 0 }
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 123 of file localtime.c.

#define DAY_OF_YEAR   1

Definition at line 162 of file localtime.c.

Referenced by getrule(), and transtime().

#define JULIAN_DAY   0

Definition at line 161 of file localtime.c.

Referenced by getrule(), and transtime().

#define MONTH_NTH_DAY_OF_WEEK   2

Definition at line 163 of file localtime.c.

Referenced by getrule(), and transtime().

#define MY_TZNAME_MAX   255

Definition at line 129 of file localtime.c.

#define OPEN_MODE   O_RDONLY

Definition at line 91 of file localtime.c.

Referenced by tzload().

#define TZ_ABBR_CHAR_SET   "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 :+-._"

Definition at line 75 of file localtime.c.

#define TZ_ABBR_ERR_CHAR   '_'

Definition at line 80 of file localtime.c.

#define TZ_ABBR_MAX_LEN   16

Definition at line 71 of file localtime.c.

#define TZ_STRLEN_MAX   255

Definition at line 132 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 105 of file localtime.c.

Referenced by tzparse().


Function Documentation

void ast_get_dst_info ( const time_t *const   timep,
int *  dst_enabled,
time_t *  dst_start,
time_t *  dst_end,
int *  gmt_off,
const char *const   zone 
)

Definition at line 1155 of file localtime.c.

References ast_tzset(), state::ats, AVGSECSPERYEAR, state::goahead, state::goback, state::timecnt, ttinfo::tt_gmtoff, ttinfo::tt_isdst, state::ttis, state::typecnt, state::types, and YEARSPERREPEAT.

Referenced by set_timezone_variables().

01156 {
01157    int i;   
01158    int transition1 = -1;
01159    int transition2 = -1;
01160    time_t      seconds;
01161    int  bounds_exceeded = 0;
01162    time_t  t = *timep;
01163    const struct state *sp;
01164    
01165    if (NULL == dst_enabled)
01166       return;
01167    *dst_enabled = 0;
01168 
01169    if (NULL == dst_start || NULL == dst_end || NULL == gmt_off)
01170       return;
01171 
01172    *gmt_off = 0; 
01173    
01174    sp = ast_tzset(zone);
01175    if (NULL == sp) 
01176       return;
01177    
01178    /* If the desired time exceeds the bounds of the defined time transitions  
01179    * then give give up on determining DST info and simply look for gmt offset 
01180    * This requires that I adjust the given time using increments of Gregorian 
01181    * repeats to place the time within the defined time transitions in the 
01182    * timezone structure.  
01183    */
01184    if ((sp->goback && t < sp->ats[0]) ||
01185          (sp->goahead && t > sp->ats[sp->timecnt - 1])) {
01186       time_t      tcycles;
01187       int_fast64_t   icycles;
01188 
01189       if (t < sp->ats[0])
01190          seconds = sp->ats[0] - t;
01191       else  seconds = t - sp->ats[sp->timecnt - 1];
01192       --seconds;
01193       tcycles = seconds / YEARSPERREPEAT / AVGSECSPERYEAR;
01194       ++tcycles;
01195       icycles = tcycles;
01196       if (tcycles - icycles >= 1 || icycles - tcycles >= 1)
01197          return;
01198       seconds = icycles;
01199       seconds *= YEARSPERREPEAT;
01200       seconds *= AVGSECSPERYEAR;
01201       if (t < sp->ats[0])
01202          t += seconds;
01203       else
01204          t -= seconds;
01205       
01206       if (t < sp->ats[0] || t > sp->ats[sp->timecnt - 1])
01207          return;  /* "cannot happen" */
01208 
01209       bounds_exceeded = 1;
01210    }
01211 
01212    if (sp->timecnt == 0 || t < sp->ats[0]) {
01213       /* I have no transition times or I'm before time */
01214       *dst_enabled = 0;
01215       /* Find where I can get gmtoff */
01216       i = 0;
01217       while (sp->ttis[i].tt_isdst)
01218          if (++i >= sp->typecnt) {
01219          i = 0;
01220          break;
01221          }
01222          *gmt_off = sp->ttis[i].tt_gmtoff;
01223          return;
01224    } 
01225 
01226    for (i = 1; i < sp->timecnt; ++i) {
01227       if (t < sp->ats[i]) {
01228          transition1 = sp->types[i - 1];
01229          transition2 = sp->types[i];
01230          break;
01231       } 
01232    }
01233    /* if I found transition times that do not bounded the given time and these correspond to 
01234       or the bounding zones do not reflect a changes in day light savings, then I do not have dst active */
01235    if (i >= sp->timecnt || 0 > transition1 || 0 > transition2 ||
01236          (sp->ttis[transition1].tt_isdst == sp->ttis[transition2].tt_isdst)) {
01237       *dst_enabled = 0;
01238       *gmt_off     = sp->ttis[sp->types[sp->timecnt -1]].tt_gmtoff;
01239    } else {
01240       /* I have valid daylight savings information. */
01241       if(sp->ttis[transition2].tt_isdst) 
01242          *gmt_off = sp->ttis[transition1].tt_gmtoff;
01243       else 
01244          *gmt_off = sp->ttis[transition2].tt_gmtoff;
01245 
01246       /* If I adjusted the time earlier, indicate that the dst is invalid */
01247       if (!bounds_exceeded) {
01248          *dst_enabled = 1;
01249          /* Determine which of the bounds is the start of daylight savings and which is the end */
01250          if(sp->ttis[transition2].tt_isdst) {
01251             *dst_start = sp->ats[i];
01252             *dst_end = sp->ats[i -1];
01253          } else {
01254             *dst_start = sp->ats[i -1];
01255             *dst_end = sp->ats[i];
01256          }
01257       }
01258    }  
01259    return;
01260 }

struct ast_tm* ast_localtime ( const struct timeval *  timep,
struct ast_tm tmp,
const char *  zone 
) [read]

Definition at line 1140 of file localtime.c.

References ast_tzset(), and localsub().

Referenced by __ast_verbose_ap(), 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_fr(), ast_say_date_gr(), ast_say_date_he(), ast_say_date_hu(), ast_say_date_ka(), ast_say_date_nl(), ast_say_date_pt(), ast_say_date_th(), 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_th(), 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_hu(), ast_say_datetime_ka(), ast_say_datetime_nl(), ast_say_datetime_pt(), ast_say_datetime_pt_BR(), ast_say_datetime_th(), ast_say_datetime_zh(), ast_say_time_de(), ast_say_time_en(), ast_say_time_fr(), ast_say_time_gr(), ast_say_time_he(), ast_say_time_hu(), ast_say_time_ka(), ast_say_time_nl(), ast_say_time_pt(), ast_say_time_pt_BR(), ast_say_time_th(), ast_say_time_zh(), build_device(), build_radius_record(), callerid_genmsg(), cdr_get_tv(), cli_prompt(), enc_ie_date(), execute_cb(), find_conf_realtime(), get_date(), handle_minivm_show_stats(), handle_show_settings(), handle_time_date_req_message(), httpd_helper_thread(), iax2_datetime(), isodate(), leave_voicemail(), main(), make_email_file(), manager_log(), packdate(), pgsql_log(), phone_call(), phoneprov_callback(), play_message_datetime(), prep_email_sub_vars(), rpt_localtime(), say_date_generic(), send_date_time(), send_date_time2(), send_date_time3(), sendmail(), set_timezone_variables(), sip_show_registry(), sms_compose2(), sms_handleincoming_proto2(), sqlite_log(), static_callback(), timeout_write(), transmit_notify_request_with_callerid(), vmu_tm(), write_history(), and write_metadata().

01141 {
01142    const struct state *sp = ast_tzset(zone);
01143    memset(tmp, 0, sizeof(*tmp));
01144    return sp ? localsub(timep, 0L, tmp, sp) : NULL;
01145 }

struct timeval ast_mktime ( struct ast_tm tmp,
const char *  zone 
) [read]

Definition at line 1755 of file localtime.c.

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

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

01756 {
01757    const struct state *sp;
01758    if (!(sp = ast_tzset(zone)))
01759       return WRONG;
01760    return time1(tmp, localsub, 0L, sp);
01761 }

int ast_strftime ( char *  buf,
size_t  len,
const char *  tmp,
const struct ast_tm tm 
)

Definition at line 1763 of file localtime.c.

References ast_calloc, ast_free, ast_realloc, format, and ast_tm::tm_usec.

Referenced by __ast_verbose_ap(), acf_strftime(), action_corestatus(), append_date(), ast_log(), build_radius_record(), cdr_get_tv(), cli_prompt(), dump_datetime(), execute_cb(), find_conf_realtime(), get_date(), handle_minivm_show_stats(), handle_show_settings(), httpd_helper_thread(), isodate(), leave_voicemail(), make_email_file(), manager_log(), pgsql_log(), phoneprov_callback(), prep_email_sub_vars(), sendmail(), sendpage(), sip_show_registry(), sqlite_log(), static_callback(), timeout_write(), and write_metadata().

01764 {
01765    size_t fmtlen = strlen(tmp) + 1;
01766    char *format = ast_calloc(1, fmtlen), *fptr = format, *newfmt;
01767    int decimals = -1, i, res;
01768    long fraction;
01769 
01770    if (!format)
01771       return -1;
01772    for (; *tmp; tmp++) {
01773       if (*tmp == '%') {
01774          switch (tmp[1]) {
01775          case '1':
01776          case '2':
01777          case '3':
01778          case '4':
01779          case '5':
01780          case '6':
01781             if (tmp[2] != 'q')
01782                goto defcase;
01783             decimals = tmp[1] - '0';
01784             tmp++;
01785             /* Fall through */
01786          case 'q': /* Milliseconds */
01787             if (decimals == -1)
01788                decimals = 3;
01789 
01790             /* Juggle some memory to fit the item */
01791             newfmt = ast_realloc(format, fmtlen + decimals);
01792             if (!newfmt) {
01793                ast_free(format);
01794                return -1;
01795             }
01796             fptr = fptr - format + newfmt;
01797             format = newfmt;
01798             fmtlen += decimals;
01799 
01800             /* Reduce the fraction of time to the accuracy needed */
01801             for (i = 6, fraction = tm->tm_usec; i > decimals; i--)
01802                fraction /= 10;
01803             fptr += sprintf(fptr, "%0*ld", decimals, fraction);
01804 
01805             /* Reset, in case more than one 'q' specifier exists */
01806             decimals = -1;
01807             tmp++;
01808             break;
01809          default:
01810             goto defcase;
01811          }
01812       } else
01813 defcase: *fptr++ = *tmp;
01814    }
01815    *fptr = '\0';
01816 #undef strftime
01817    res = (int)strftime(buf, len, format, (struct tm *)tm);
01818    ast_free(format);
01819    return res;
01820 }

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

Definition at line 1010 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_get_dst_info(), ast_localtime(), and ast_mktime().

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

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

Referenced by tzload().

00229 {
00230    long  result;
00231    int   i;
00232 
00233    result = (codep[0] & 0x80) ? ~0L : 0;
00234    for (i = 0; i < 4; ++i)
00235       result = (result << 8) | (codep[i] & 0xff);
00236    return result;
00237 }

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

Definition at line 239 of file localtime.c.

Referenced by tzload().

00240 {
00241    time_t   result;
00242    int   i;
00243 
00244    result = (codep[0] & 0x80) ?  (~(int_fast64_t) 0) : 0;
00245    for (i = 0; i < 8; ++i)
00246       result = result * 256 + (codep[i] & 0xff);
00247    return result;
00248 }

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

Definition at line 250 of file localtime.c.

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

Referenced by tzload().

00251 {
00252    const long long at1 = t1, at0 = t0;
00253    if (TYPE_INTEGRAL(time_t) &&
00254       TYPE_BIT(time_t) - TYPE_SIGNED(time_t) < SECSPERREPEAT_BITS)
00255          return 0;
00256    return at1 - at0 == SECSPERREPEAT;
00257 }

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

References is_digit, and num.

Referenced by getrule(), and getsecs().

00540 {
00541    char  c;
00542    int   num;
00543 
00544    if (strp == NULL || !is_digit(c = *strp))
00545       return NULL;
00546    num = 0;
00547    do {
00548       num = num * 10 + (c - '0');
00549       if (num > max)
00550          return NULL;   /* illegal value */
00551       c = *++strp;
00552    } while (is_digit(c));
00553    if (num < min)
00554       return NULL;      /* illegal value */
00555    *nump = num;
00556    return strp;
00557 }

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

References getsecs().

Referenced by tzparse().

00607 {
00608    int   neg = 0;
00609 
00610    if (*strp == '-') {
00611       neg = 1;
00612       ++strp;
00613    } else if (*strp == '+')
00614       ++strp;
00615    strp = getsecs(strp, offsetp);
00616    if (strp == NULL)
00617       return NULL;      /* illegal time */
00618    if (neg)
00619       *offsetp = -*offsetp;
00620    return strp;
00621 }

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

Referenced by tzparse().

00524 {
00525    int   c;
00526 
00527    while ((c = *strp) != '\0' && c != delim)
00528       ++strp;
00529    return strp;
00530 }

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

References DAY_OF_YEAR, DAYSPERLYEAR, 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().

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

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

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

Referenced by getoffset(), and getrule().

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

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

References is_digit.

Referenced by tzparse().

00505 {
00506    char  c;
00507 
00508    while ((c = *strp) != '\0' && !is_digit(c) && c != ',' && c != '-' &&
00509       c != '+')
00510          ++strp;
00511    return strp;
00512 }

static int gmtload ( struct state sp  )  [static]

Definition at line 1002 of file localtime.c.

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

Referenced by ast_tzset(), and gmtsub().

01003 {
01004    if (tzload(gmt, sp, TRUE) != 0)
01005       return tzparse(gmt, sp, TRUE);
01006    else
01007       return -1;
01008 }

static struct ast_tm* gmtsub ( const struct timeval *  timep,
const long  offset,
struct ast_tm tmp 
) [static, read]

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

01267 {
01268    struct ast_tm *   result;
01269    struct state *sp;
01270 
01271    AST_LIST_LOCK(&zonelist);
01272    AST_LIST_TRAVERSE(&zonelist, sp, list) {
01273       if (!strcmp(sp->name, "UTC"))
01274          break;
01275    }
01276 
01277    if (!sp) {
01278       if (!(sp = (struct state *) ast_calloc(1, sizeof *sp)))
01279          return NULL;
01280       gmtload(sp);
01281       AST_LIST_INSERT_TAIL(&zonelist, sp, list);
01282    }
01283    AST_LIST_UNLOCK(&zonelist);
01284 
01285    result = timesub(timep, offset, sp, tmp);
01286 #ifdef TM_ZONE
01287    /*
01288    ** Could get fancy here and deliver something such as
01289    ** "UTC+xxxx" or "UTC-xxxx" if offset is non-zero,
01290    ** but this is no time for a treasure hunt.
01291    */
01292    if (offset != 0)
01293       tmp->TM_ZONE = "    ";
01294    else
01295       tmp->TM_ZONE = sp->chars;
01296 #endif /* defined TM_ZONE */
01297    return result;
01298 }

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

Simplified normalize logic courtesy Paul Eggert.

Note:
Adapted from code provided by Robert Elz, who writes: The "best" way to do mktime I think is based on an idea of Bob Kridle's (so its said...) from a long time ago. It does a binary search of the time_t space. Since time_t's are just 32 bits, its a max of 32 iterations (even at 64 bits it would still be very reasonable).

Definition at line 1449 of file localtime.c.

Referenced by normalize_overflow(), time2sub(), and timesub().

01450 {
01451    int   number0;
01452 
01453    number0 = *number;
01454    *number += delta;
01455    return (*number < number0) != (delta < 0);
01456 }

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

Referenced by timesub().

01306 {
01307    return (y >= 0) ? (y / 4 - y / 100 + y / 400) :
01308       -(leaps_thru_end_of(-(y + 1)) + 1);
01309 }

static struct ast_tm* localsub ( const struct timeval *  timep,
const long  offset,
struct ast_tm tmp,
const struct state sp 
) [static, read]

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

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

Referenced by ast_localtime(), and ast_mktime().

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

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

Definition at line 1458 of file localtime.c.

Referenced by long_normalize_overflow(), and time2sub().

01459 {
01460    long  number0;
01461 
01462    number0 = *number;
01463    *number += delta;
01464    return (*number < number0) != (delta < 0);
01465 }

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

Definition at line 1478 of file localtime.c.

References long_increment_overflow().

Referenced by time2sub().

01479 {
01480    int   tensdelta;
01481 
01482    tensdelta = (*unitsptr >= 0) ?
01483       (*unitsptr / base) :
01484       (-1 - (-1 - *unitsptr) / base);
01485    *unitsptr -= tensdelta * base;
01486    return long_increment_overflow(tensptr, tensdelta);
01487 }

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

Definition at line 1467 of file localtime.c.

References increment_overflow().

Referenced by time2sub().

01468 {
01469    int   tensdelta;
01470 
01471    tensdelta = (*unitsptr >= 0) ?
01472       (*unitsptr / base) :
01473       (-1 - (-1 - *unitsptr) / base);
01474    *unitsptr -= tensdelta * base;
01475    return increment_overflow(tensptr, tensdelta);
01476 }

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 ast_tm *atmp, const struct ast_tm *btmp)   )  [static]

static struct ast_tm* timesub P ( (const struct timeval *timep, long offset, const struct state *sp, struct ast_tm *tmp)   )  [static, read]

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

static struct timeval time2 P ( (struct ast_tm *tmp, struct ast_tm *(*funcp) P((const struct timeval *, long, struct ast_tm *, const struct state *sp)), long offset, int *okayp, const struct state *sp)   )  [static, read]

static struct timeval time1 P ( (struct ast_tm *tmp, struct ast_tm *(*funcp) P((const struct timeval *, long, struct ast_tm *, const struct state *sp)), long offset, const struct state *sp)   )  [static, read]

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 ast_tm* localsub P ( (const struct timeval *timep, long offset, struct ast_tm *tmp, const struct state *sp)   )  [static, read]

static struct ast_tm* gmtsub P ( (const struct timeval *timep, long offset, struct ast_tm *tmp)   )  [static, read]

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 struct timeval time1 ( struct ast_tm tmp,
struct ast_tm *(*)(const struct timeval *, long, struct ast_tm *, const struct state *)  funcp,
const long  offset,
const struct state sp 
) [static, read]

Definition at line 1690 of file localtime.c.

References FALSE, time2(), state::timecnt, TRUE, ttinfo::tt_gmtoff, ttinfo::tt_isdst, state::ttis, state::typecnt, state::types, and TZ_MAX_TYPES.

Referenced by ast_mktime().

01691 {
01692    struct timeval       t;
01693    int         samei, otheri;
01694    int         sameind, otherind;
01695    int         i;
01696    int         nseen;
01697    int            seen[TZ_MAX_TYPES];
01698    int            types[TZ_MAX_TYPES];
01699    int            okay;
01700 
01701    if (tmp->tm_isdst > 1)
01702       tmp->tm_isdst = 1;
01703    t = time2(tmp, funcp, offset, &okay, sp);
01704 #ifdef PCTS
01705    /*
01706    ** PCTS code courtesy Grant Sullivan.
01707    */
01708    if (okay)
01709       return t;
01710    if (tmp->tm_isdst < 0)
01711       tmp->tm_isdst = 0;   /* reset to std and try again */
01712 #endif /* defined PCTS */
01713 #ifndef PCTS
01714    if (okay || tmp->tm_isdst < 0)
01715       return t;
01716 #endif /* !defined PCTS */
01717    /*
01718    ** We're supposed to assume that somebody took a time of one type
01719    ** and did some math on it that yielded a "struct ast_tm" that's bad.
01720    ** We try to divine the type they started from and adjust to the
01721    ** type they need.
01722    */
01723    if (sp == NULL)
01724       return WRONG;
01725    for (i = 0; i < sp->typecnt; ++i)
01726       seen[i] = FALSE;
01727    nseen = 0;
01728    for (i = sp->timecnt - 1; i >= 0; --i)
01729       if (!seen[sp->types[i]]) {
01730          seen[sp->types[i]] = TRUE;
01731          types[nseen++] = sp->types[i];
01732       }
01733    for (sameind = 0; sameind < nseen; ++sameind) {
01734       samei = types[sameind];
01735       if (sp->ttis[samei].tt_isdst != tmp->tm_isdst)
01736          continue;
01737       for (otherind = 0; otherind < nseen; ++otherind) {
01738          otheri = types[otherind];
01739          if (sp->ttis[otheri].tt_isdst == tmp->tm_isdst)
01740             continue;
01741          tmp->tm_sec += sp->ttis[otheri].tt_gmtoff -
01742                sp->ttis[samei].tt_gmtoff;
01743          tmp->tm_isdst = !tmp->tm_isdst;
01744          t = time2(tmp, funcp, offset, &okay, sp);
01745          if (okay)
01746             return t;
01747          tmp->tm_sec -= sp->ttis[otheri].tt_gmtoff -
01748                sp->ttis[samei].tt_gmtoff;
01749          tmp->tm_isdst = !tmp->tm_isdst;
01750       }
01751    }
01752    return WRONG;
01753 }

static struct timeval time2 ( struct ast_tm tmp,
struct ast_tm *(*)(const struct timeval *, long, struct ast_tm *, const struct state *sp)  funcp,
const long  offset,
int *  okayp,
const struct state sp 
) [static, read]

Note:
First try without normalization of seconds (in case tm_sec contains a value associated with a leap second). If that fails, try with normalization of seconds.

Definition at line 1677 of file localtime.c.

References FALSE, time2sub(), and TRUE.

Referenced by time1().

01678 {
01679    struct timeval t;
01680 
01681    /*! \note
01682    ** First try without normalization of seconds
01683    ** (in case tm_sec contains a value associated with a leap second).
01684    ** If that fails, try with normalization of seconds.
01685    */
01686    t = time2sub(tmp, funcp, offset, okayp, FALSE, sp);
01687    return *okayp ? t : time2sub(tmp, funcp, offset, okayp, TRUE, sp);
01688 }

static struct timeval time2sub ( struct ast_tm tmp,
struct ast_tm *(*)(const struct timeval *, long, struct ast_tm *, const struct state *)  funcp,
const long  offset,
int *  okayp,
const int  do_norm_secs,
const struct state sp 
) [static, read]

Definition at line 1503 of file localtime.c.

References DAYSPERLYEAR, dir, EPOCH_YEAR, FALSE, HOURSPERDAY, increment_overflow(), isleap, long_increment_overflow(), long_normalize_overflow(), MINSPERHOUR, mon_lengths, MONSPERYEAR, normalize_overflow(), SECSPERMIN, ast_tm::tm_hour, ast_tm::tm_isdst, ast_tm::tm_mday, ast_tm::tm_min, ast_tm::tm_mon, ast_tm::tm_sec, ast_tm::tm_year, TM_YEAR_BASE, tmcomp(), TRUE, TYPE_BIT, TYPE_INTEGRAL, TYPE_SIGNED, and year_lengths.

Referenced by time2().

01504 {
01505    int         dir;
01506    int         i, j;
01507    int         saved_seconds;
01508    long        li;
01509    time_t         lo;
01510    time_t         hi;
01511    long           y;
01512    struct timeval       newt = { 0, 0 };
01513    struct timeval       t = { 0, 0 };
01514    struct ast_tm        yourtm, mytm;
01515 
01516    *okayp = FALSE;
01517    yourtm = *tmp;
01518    if (do_norm_secs) {
01519       if (normalize_overflow(&yourtm.tm_min, &yourtm.tm_sec,
01520          SECSPERMIN))
01521             return WRONG;
01522    }
01523    if (normalize_overflow(&yourtm.tm_hour, &yourtm.tm_min, MINSPERHOUR))
01524       return WRONG;
01525    if (normalize_overflow(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY))
01526       return WRONG;
01527    y = yourtm.tm_year;
01528    if (long_normalize_overflow(&y, &yourtm.tm_mon, MONSPERYEAR))
01529       return WRONG;
01530    /*
01531    ** Turn y into an actual year number for now.
01532    ** It is converted back to an offset from TM_YEAR_BASE later.
01533    */
01534    if (long_increment_overflow(&y, TM_YEAR_BASE))
01535       return WRONG;
01536    while (yourtm.tm_mday <= 0) {
01537       if (long_increment_overflow(&y, -1))
01538          return WRONG;
01539       li = y + (1 < yourtm.tm_mon);
01540       yourtm.tm_mday += year_lengths[isleap(li)];
01541    }
01542    while (yourtm.tm_mday > DAYSPERLYEAR) {
01543       li = y + (1 < yourtm.tm_mon);
01544       yourtm.tm_mday -= year_lengths[isleap(li)];
01545       if (long_increment_overflow(&y, 1))
01546          return WRONG;
01547    }
01548    for ( ; ; ) {
01549       i = mon_lengths[isleap(y)][yourtm.tm_mon];
01550       if (yourtm.tm_mday <= i)
01551          break;
01552       yourtm.tm_mday -= i;
01553       if (++yourtm.tm_mon >= MONSPERYEAR) {
01554          yourtm.tm_mon = 0;
01555          if (long_increment_overflow(&y, 1))
01556             return WRONG;
01557       }
01558    }
01559    if (long_increment_overflow(&y, -TM_YEAR_BASE))
01560       return WRONG;
01561    yourtm.tm_year = y;
01562    if (yourtm.tm_year != y)
01563       return WRONG;
01564    if (yourtm.tm_sec >= 0 && yourtm.tm_sec < SECSPERMIN)
01565       saved_seconds = 0;
01566    else if (y + TM_YEAR_BASE < EPOCH_YEAR) {
01567       /*
01568       ** We can't set tm_sec to 0, because that might push the
01569       ** time below the minimum representable time.
01570       ** Set tm_sec to 59 instead.
01571       ** This assumes that the minimum representable time is
01572       ** not in the same minute that a leap second was deleted from,
01573       ** which is a safer assumption than using 58 would be.
01574       */
01575       if (increment_overflow(&yourtm.tm_sec, 1 - SECSPERMIN))
01576          return WRONG;
01577       saved_seconds = yourtm.tm_sec;
01578       yourtm.tm_sec = SECSPERMIN - 1;
01579    } else {
01580       saved_seconds = yourtm.tm_sec;
01581       yourtm.tm_sec = 0;
01582    }
01583    /*
01584    ** Do a binary search (this works whatever time_t's type is).
01585    */
01586    if (!TYPE_SIGNED(time_t)) {
01587       lo = 0;
01588       hi = lo - 1;
01589    } else if (!TYPE_INTEGRAL(time_t)) {
01590       if (sizeof(time_t) > sizeof(float))
01591          hi = (time_t) DBL_MAX;
01592       else  hi = (time_t) FLT_MAX;
01593       lo = -hi;
01594    } else {
01595       lo = 1;
01596       for (i = 0; i < (int) TYPE_BIT(time_t) - 1; ++i)
01597          lo *= 2;
01598       hi = -(lo + 1);
01599    }
01600    for ( ; ; ) {
01601       t.tv_sec = lo / 2 + hi / 2;
01602       if (t.tv_sec < lo)
01603          t.tv_sec = lo;
01604       else if (t.tv_sec > hi)
01605          t.tv_sec = hi;
01606       if ((*funcp)(&t, offset, &mytm, sp) == NULL) {
01607          /*
01608          ** Assume that t is too extreme to be represented in
01609          ** a struct ast_tm; arrange things so that it is less
01610          ** extreme on the next pass.
01611          */
01612          dir = (t.tv_sec > 0) ? 1 : -1;
01613       } else   dir = tmcomp(&mytm, &yourtm);
01614       if (dir != 0) {
01615          if (t.tv_sec == lo) {
01616             ++t.tv_sec;
01617             if (t.tv_sec <= lo)
01618                return WRONG;
01619             ++lo;
01620          } else if (t.tv_sec == hi) {
01621             --t.tv_sec;
01622             if (t.tv_sec >= hi)
01623                return WRONG;
01624             --hi;
01625          }
01626          if (lo > hi)
01627             return WRONG;
01628          if (dir > 0)
01629             hi = t.tv_sec;
01630          else  lo = t.tv_sec;
01631          continue;
01632       }
01633       if (yourtm.tm_isdst < 0 || mytm.tm_isdst == yourtm.tm_isdst)
01634          break;
01635       /*
01636       ** Right time, wrong type.
01637       ** Hunt for right time, right type.
01638       ** It's okay to guess wrong since the guess
01639       ** gets checked.
01640       */
01641       /*
01642       ** The (void *) casts are the benefit of SunOS 3.3 on Sun 2's.
01643       */
01644       for (i = sp->typecnt - 1; i >= 0; --i) {
01645          if (sp->ttis[i].tt_isdst != yourtm.tm_isdst)
01646             continue;
01647          for (j = sp->typecnt - 1; j >= 0; --j) {
01648             if (sp->ttis[j].tt_isdst == yourtm.tm_isdst)
01649                continue;
01650             newt.tv_sec = t.tv_sec + sp->ttis[j].tt_gmtoff -
01651                sp->ttis[i].tt_gmtoff;
01652             if ((*funcp)(&newt, offset, &mytm, sp) == NULL)
01653                continue;
01654             if (tmcomp(&mytm, &yourtm) != 0)
01655                continue;
01656             if (mytm.tm_isdst != yourtm.tm_isdst)
01657                continue;
01658             /*
01659             ** We have a match.
01660             */
01661             t = newt;
01662             goto label;
01663          }
01664       }
01665       return WRONG;
01666    }
01667 label:
01668    newt.tv_sec = t.tv_sec + saved_seconds;
01669    if ((newt.tv_sec < t.tv_sec) != (saved_seconds < 0))
01670       return WRONG;
01671    t.tv_sec = newt.tv_sec;
01672    if ((*funcp)(&t, offset, tmp, sp))
01673       *okayp = TRUE;
01674    return t;
01675 }

static struct ast_tm* timesub ( const struct timeval *  timep,
const long  offset,
const struct state sp,
struct ast_tm tmp 
) [static, read]

Definition at line 1311 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, ast_tm::tm_hour, ast_tm::tm_isdst, ast_tm::tm_mday, ast_tm::tm_min, ast_tm::tm_mon, ast_tm::tm_sec, ast_tm::tm_usec, ast_tm::tm_wday, ast_tm::tm_yday, ast_tm::tm_year, TM_YEAR_BASE, and year_lengths.

Referenced by gmtsub(), and localsub().

01312 {
01313    const struct lsinfo *   lp;
01314    time_t         tdays;
01315    int         idays;   /* unsigned would be so 2003 */
01316    long        rem;
01317    int            y;
01318    const int *    ip;
01319    long        corr;
01320    int         hit;
01321    int         i;
01322    long  seconds;
01323 
01324 
01325    corr = 0;
01326    hit = 0;
01327    i = (sp == NULL) ? 0 : sp->leapcnt;
01328    while (--i >= 0) {
01329       lp = &sp->lsis[i];
01330       if (timep->tv_sec >= lp->ls_trans) {
01331          if (timep->tv_sec == lp->ls_trans) {
01332             hit = ((i == 0 && lp->ls_corr > 0) ||
01333                lp->ls_corr > sp->lsis[i - 1].ls_corr);
01334             if (hit)
01335                while (i > 0 &&
01336                   sp->lsis[i].ls_trans ==
01337                   sp->lsis[i - 1].ls_trans + 1 &&
01338                   sp->lsis[i].ls_corr ==
01339                   sp->lsis[i - 1].ls_corr + 1) {
01340                      ++hit;
01341                      --i;
01342                }
01343          }
01344          corr = lp->ls_corr;
01345          break;
01346       }
01347    }
01348    y = EPOCH_YEAR;
01349    tdays = timep->tv_sec / SECSPERDAY;
01350    rem = timep->tv_sec - tdays * SECSPERDAY;
01351    while (tdays < 0 || tdays >= year_lengths[isleap(y)]) {
01352       int      newy;
01353       time_t   tdelta;
01354       int   idelta;
01355       int   leapdays;
01356 
01357       tdelta = tdays / DAYSPERLYEAR;
01358       idelta = tdelta;
01359       if (tdelta - idelta >= 1 || idelta - tdelta >= 1)
01360          return NULL;
01361       if (idelta == 0)
01362          idelta = (tdays < 0) ? -1 : 1;
01363       newy = y;
01364       if (increment_overflow(&newy, idelta))
01365          return NULL;
01366       leapdays = leaps_thru_end_of(newy - 1) -
01367          leaps_thru_end_of(y - 1);
01368       tdays -= ((time_t) newy - y) * DAYSPERNYEAR;
01369       tdays -= leapdays;
01370       y = newy;
01371    }
01372 
01373    seconds = tdays * SECSPERDAY + 0.5;
01374    tdays = seconds / SECSPERDAY;
01375    rem += seconds - tdays * SECSPERDAY;
01376 
01377    /*
01378    ** Given the range, we can now fearlessly cast...
01379    */
01380    idays = tdays;
01381    rem += offset - corr;
01382    while (rem < 0) {
01383       rem += SECSPERDAY;
01384       --idays;
01385    }
01386    while (rem >= SECSPERDAY) {
01387       rem -= SECSPERDAY;
01388       ++idays;
01389    }
01390    while (idays < 0) {
01391       if (increment_overflow(&y, -1))
01392          return NULL;
01393       idays += year_lengths[isleap(y)];
01394    }
01395    while (idays >= year_lengths[isleap(y)]) {
01396       idays -= year_lengths[isleap(y)];
01397       if (increment_overflow(&y, 1))
01398          return NULL;
01399    }
01400    tmp->tm_year = y;
01401    if (increment_overflow(&tmp->tm_year, -TM_YEAR_BASE))
01402       return NULL;
01403    tmp->tm_yday = idays;
01404    /*
01405    ** The "extra" mods below avoid overflow problems.
01406    */
01407    tmp->tm_wday = EPOCH_WDAY +
01408       ((y - EPOCH_YEAR) % DAYSPERWEEK) *
01409       (DAYSPERNYEAR % DAYSPERWEEK) +
01410       leaps_thru_end_of(y - 1) -
01411       leaps_thru_end_of(EPOCH_YEAR - 1) +
01412       idays;
01413    tmp->tm_wday %= DAYSPERWEEK;
01414    if (tmp->tm_wday < 0)
01415       tmp->tm_wday += DAYSPERWEEK;
01416    tmp->tm_hour = (int) (rem / SECSPERHOUR);
01417    rem %= SECSPERHOUR;
01418    tmp->tm_min = (int) (rem / SECSPERMIN);
01419    /*
01420    ** A positive leap second requires a special
01421    ** representation. This uses "... ??:59:60" et seq.
01422    */
01423    tmp->tm_sec = (int) (rem % SECSPERMIN) + hit;
01424    ip = mon_lengths[isleap(y)];
01425    for (tmp->tm_mon = 0; idays >= ip[tmp->tm_mon]; ++(tmp->tm_mon))
01426       idays -= ip[tmp->tm_mon];
01427    tmp->tm_mday = (int) (idays + 1);
01428    tmp->tm_isdst = 0;
01429 #ifdef TM_GMTOFF
01430    tmp->TM_GMTOFF = offset;
01431 #endif /* defined TM_GMTOFF */
01432    tmp->tm_usec = timep->tv_usec;
01433    return tmp;
01434 }

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

Definition at line 1489 of file localtime.c.

References ast_tm::tm_hour, ast_tm::tm_mday, ast_tm::tm_min, ast_tm::tm_mon, ast_tm::tm_sec, ast_tm::tm_usec, and ast_tm::tm_year.

Referenced by time2sub().

01490 {
01491    int   result;
01492 
01493    if ((result = (atmp->tm_year - btmp->tm_year)) == 0 &&
01494       (result = (atmp->tm_mon - btmp->tm_mon)) == 0 &&
01495       (result = (atmp->tm_mday - btmp->tm_mday)) == 0 &&
01496       (result = (atmp->tm_hour - btmp->tm_hour)) == 0 &&
01497       (result = (atmp->tm_min - btmp->tm_min)) == 0 &&
01498       (result = (atmp->tm_sec - btmp->tm_sec)) == 0)
01499          result = atmp->tm_usec - btmp->tm_usec;
01500    return result;
01501 }

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

References DAY_OF_YEAR, DAYSPERWEEK, INITIALIZE, isleap, JULIAN_DAY, m1, mon_lengths, 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().

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

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

Definition at line 259 of file localtime.c.

References state::ats, buf, state::charcnt, state::chars, detzcode(), detzcode64(), differ_by_repeat(), FALSE, FILENAME_MAX, state::goahead, state::goback, state::leapcnt, lsinfo::ls_corr, lsinfo::ls_trans, state::lsis, OPEN_MODE, state::timecnt, TRUE, ttinfo::tt_abbrind, ttinfo::tt_gmtoff, ttinfo::tt_isdst, ttinfo::tt_ttisgmt, ttinfo::tt_ttisstd, state::ttis, TYPE_INTEGRAL, TYPE_SIGNED, state::typecnt, state::types, TZ_MAX_CHARS, TZ_MAX_LEAPS, TZ_MAX_TIMES, TZ_MAX_TYPES, TZDEFAULT, TZDIR, tzparse(), and YEARSPERREPEAT.

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

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

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

References state::ats, state::charcnt, state::chars, EPOCH_YEAR, FALSE, getoffset(), getqzname(), getrule(), getzname(), INITIALIZE, isleap, state::leapcnt, SECSPERDAY, SECSPERHOUR, starttime, state::timecnt, transtime(), TRUE, 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 year_lengths.

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

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


Variable Documentation

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

Definition at line 66 of file localtime.c.

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

Definition at line 94 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 489 of file localtime.c.

Referenced by time2sub(), timesub(), and transtime().

struct timeval WRONG = { 0, 0 } [static]

Definition at line 95 of file localtime.c.

const int year_lengths[2] [static]

Initial value:

Definition at line 494 of file localtime.c.

Referenced by time2sub(), timesub(), and tzparse().


Generated on Wed Oct 28 11:52:48 2009 for Asterisk - the Open Source PBX by  doxygen 1.5.6