Wed Aug 18 22:34:26 2010

Asterisk developer's documentation


localtime.c File Reference

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

Go to the source code of this file.

Data Structures

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

Defines

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

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)
ast_tmast_localtime (const struct timeval *timep, struct ast_tm *tmp, const char *zone)
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 124 of file localtime.c.

#define DAY_OF_YEAR   1

Definition at line 163 of file localtime.c.

Referenced by getrule(), and transtime().

#define JULIAN_DAY   0

Definition at line 162 of file localtime.c.

Referenced by getrule(), and transtime().

#define MONTH_NTH_DAY_OF_WEEK   2

Definition at line 164 of file localtime.c.

Referenced by getrule(), and transtime().

#define MY_TZNAME_MAX   255

Definition at line 130 of file localtime.c.

#define OPEN_MODE   O_RDONLY

Definition at line 92 of file localtime.c.

Referenced by tzload().

#define TZ_ABBR_CHAR_SET   "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 :+-._"

Definition at line 76 of file localtime.c.

#define TZ_ABBR_ERR_CHAR   '_'

Definition at line 81 of file localtime.c.

#define TZ_ABBR_MAX_LEN   16

Definition at line 72 of file localtime.c.

#define TZ_STRLEN_MAX   255

Definition at line 133 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 106 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 1156 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().

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

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

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

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

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

Definition at line 1756 of file localtime.c.

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

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

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

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

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

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

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

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

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

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

Referenced by tzload().

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

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

Definition at line 240 of file localtime.c.

Referenced by tzload().

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

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

Definition at line 251 of file localtime.c.

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

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

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

References is_digit, and num.

Referenced by getrule(), and getsecs().

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

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

References getsecs().

Referenced by tzparse().

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

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

Referenced by tzparse().

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

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

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

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

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

Referenced by getoffset(), and getrule().

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

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

References is_digit.

Referenced by tzparse().

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

static int gmtload ( struct state sp  )  [static]

Definition at line 1003 of file localtime.c.

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

Referenced by ast_tzset(), and gmtsub().

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

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

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

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

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

Simplified normalize logic courtesy Paul Eggert.

Definition at line 1450 of file localtime.c.

Referenced by normalize_overflow(), and timesub().

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

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

Referenced by timesub().

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

static struct ast_tm* localsub ( const struct timeval *  timep,
const long  offset,
struct ast_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 1050 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().

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

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

Definition at line 1459 of file localtime.c.

Referenced by long_normalize_overflow(), and time2sub().

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

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

Definition at line 1479 of file localtime.c.

References long_increment_overflow().

Referenced by time2sub().

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

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

Definition at line 1468 of file localtime.c.

References increment_overflow().

Referenced by time2sub().

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

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]

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]

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]

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]

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]

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

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

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

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

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

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

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

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

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

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

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

Definition at line 1691 of file localtime.c.

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

Referenced by ast_mktime().

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

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]

Definition at line 1678 of file localtime.c.

References FALSE, time2sub(), and TRUE.

Referenced by time1().

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

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]

Definition at line 1504 of file localtime.c.

References DAYSPERLYEAR, dir, FALSE, HOURSPERDAY, isleap, long_increment_overflow(), long_normalize_overflow(), MINSPERHOUR, mon_lengths, MONSPERYEAR, normalize_overflow(), SECSPERMIN, ast_tm::tm_hour, ast_tm::tm_mday, ast_tm::tm_min, ast_tm::tm_mon, ast_tm::tm_sec, ast_tm::tm_year, TM_YEAR_BASE, and year_lengths.

Referenced by time2().

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

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

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

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

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

Definition at line 1490 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.

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

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

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

Referenced by tzparse().

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

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

Definition at line 260 of file localtime.c.

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

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

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

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

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

Referenced by ast_tzset(), and gmtload().

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


Variable Documentation

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

Definition at line 67 of file localtime.c.

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

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

Referenced by time2sub(), and timesub().

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

Definition at line 96 of file localtime.c.

const int year_lengths[2] [static]

Initial value:

Definition at line 495 of file localtime.c.

Referenced by time2sub(), and timesub().


Generated on Wed Aug 18 22:34:26 2010 for Asterisk - the Open Source PBX by  doxygen 1.4.7