Mon Sep 18 09:15:15 2006

Asterisk developer's documentation


localtime.c File Reference

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

Go to the source code of this file.

Data Structures

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

Defines

#define BIGGEST(a, b)   (((a) > (b)) ? (a) : (b))
#define DAY_OF_YEAR   1
#define JULIAN_DAY   0
#define LEAPS_THRU_END_OF(y)   ((y) / 4 - (y) / 100 + (y) / 400)
#define MONTH_NTH_DAY_OF_WEEK   2
#define MY_TZNAME_MAX   255
#define OPEN_MODE   O_RDONLY
#define TZ_STRLEN_MAX   255
#define WILDABBR   " "
#define WRONG   (-1)

Functions

char * ast_ctime (time_t *const timep) const
char * ast_ctime_r (time_t *const timep, char *buf) const
tm * ast_localtime (time_t *const timep, struct tm *p_tm, const char *const zone) const
time_t ast_mktime (struct tm *const tmp, const char *const zone)
 AST_MUTEX_DEFINE_STATIC (gmt_mutex)
 AST_MUTEX_DEFINE_STATIC (tzsetwall_mutex)
 AST_MUTEX_DEFINE_STATIC (tzset_mutex)
 AST_MUTEX_DEFINE_STATIC (lcl_mutex)
static long detzcode (const char *const codep)
static const char * getnum (register const char *strp, int *const nump, const int min, const int max)
 Given a pointer into a time zone string, extract a number from that string.
static const char * getoffset (register const char *strp, long *const offsetp)
 Given a pointer into a time zone string, extract an offset, in [+-]hh[:mm[:ss]] form, from the string.
static const char * getrule (const char *strp, register struct rule *const 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".
static const char * getsecs (register 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.
static void gmtload (struct state *const sp)
static void gmtsub (time_t *const timep, const long offset, struct tm *const tmp, const char *const zone) const
static int increment_overflow (int *number, int delta)
static void localsub (time_t *const timep, const long offset, struct tm *const tmp, const char *const zone) const
static int normalize_overflow (int *const tensptr, int *const unitsptr, const int base)
static int ast_tzset_basic P ((const char *name))
static int ast_tzsetwall_basic P ((void))
static int tzparse P ((const char *name, struct state *sp, int lastditch))
static int tzload P ((const char *name, struct state *sp))
static time_t transtime P ((time_t janfirst, int year, const struct rule *rulep, long offset))
static int tmcomp P ((const struct tm *atmp, const struct tm *btmp))
static void timesub P ((const time_t *timep, long offset, const struct state *sp, struct tm *tmp))
static time_t time2 P ((struct tm *tmp, void(*funcp) P((const time_t *, long, struct tm *, const char *)), long offset, int *okayp, const char *zone))
static time_t time1 P ((struct tm *tmp, void(*funcp) P((const time_t *, long, struct tm *, const char *)), long offset, const char *zone))
static int normalize_overflow P ((int *tensptr, int *unitsptr, int base))
static int increment_overflow P ((int *number, int delta))
static void gmtsub P ((const time_t *timep, long offset, struct tm *tmp, const char *zone))
static void 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 long detzcode P ((const char *codep))
static time_t time1 (struct tm *const tmp, funcp, const long offset, const char *const zone)
static time_t time2 (struct tm *const tmp, funcp, const long offset, int *const okayp, const char *const zone)
static void timesub (time_t *const timep, const long offset, const struct state *const sp, struct tm *const tmp) const
static int tmcomp (const struct tm *const atmp, const struct tm *const btmp)
static time_t transtime (time_t janfirst, const int year, const struct rule *const rulep, const long offset) const
 Given the Epoch-relative time of January 1, 00:00:00 GMT, in a year, the year, a rule, and the offset from GMT at the time that rule takes effect, calculate the Epoch-relative time that rule takes effect.
static int tzload (register const char *name, register struct state *const sp)
static int tzparse (char *name, struct state *const sp, const int lastditch) const

Variables

static const char elsieid [] = "@(#)localtime.c 7.57"
static char gmt [] = "GMT"
 FreeBSD defines 'zone' in 'struct tm' as non-const, so don't declare this string as const. time type information.
static int gmt_is_set
static struct stategmtptr = NULL
static struct statelast_lclptr = NULL
static struct statelclptr = NULL
static const int mon_lengths [2][MONSPERYEAR]
static char wildabbr [] = "WILDABBR"
static const int year_lengths [2]


Detailed Description

Multi-timezone Localtime code

Author:
Leap second handling Bradley White (bww@k.gp.cs.cmu.edu).

POSIX-style TZ environment variable handling from Guy Harris (guy@auspex.com).

Definition in file localtime.c.


Define Documentation

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

Definition at line 131 of file localtime.c.

#define DAY_OF_YEAR   1

n - day of year

Definition at line 164 of file localtime.c.

Referenced by getrule(), and transtime().

#define JULIAN_DAY   0

Jn - Julian day

Definition at line 163 of file localtime.c.

Referenced by getrule(), and transtime().

#define LEAPS_THRU_END_OF (  )     ((y) / 4 - (y) / 100 + (y) / 400)

Referenced by timesub().

#define MONTH_NTH_DAY_OF_WEEK   2

Mm.n.d - month, week, day of week

Definition at line 165 of file localtime.c.

Referenced by getrule(), and transtime().

#define MY_TZNAME_MAX   255

Definition at line 137 of file localtime.c.

#define OPEN_MODE   O_RDONLY

Definition at line 77 of file localtime.c.

Referenced by tzload().

#define TZ_STRLEN_MAX   255

Definition at line 43 of file localtime.c.

#define WILDABBR   " "

Note:
Someone might make incorrect use of a time zone abbreviation: 1. They might reference tzname[0] before calling ast_tzset (explicitly or implicitly). 2. They might reference tzname[1] before calling ast_tzset (explicitly or implicitly). 3. They might reference tzname[1] after setting to a time zone in which Daylight Saving Time is never observed. 4. They might reference tzname[0] after setting to a time zone in which Standard Time is never observed. 5. They might reference tm.TM_ZONE after calling offtime. What's best to do in the above cases is open to debate; for now, we just set things up so that in any of the five cases WILDABBR is used. Another possibility: initialize tzname[0] to the string "tzname[0] used before set", and similarly for the other cases. And another: initialize tzname[0] to "ERA", with an explanation in the manual page of what this "time zone abbreviation" means (doing this so that tzname[0] has the "normal" length of three characters).

Definition at line 106 of file localtime.c.

#define WRONG   (-1)

Definition at line 1233 of file localtime.c.

Referenced by time2().


Function Documentation

char* ast_ctime ( time_t * const  timep  )  const

Definition at line 1197 of file localtime.c.

01199 {
01200 /*
01201 ** Section 4.12.3.2 of X3.159-1989 requires that
01202 ** The ctime funciton converts the calendar time pointed to by timer
01203 ** to local time in the form of a string.  It is equivalent to
01204 **    asctime(localtime(timer))
01205 */
01206    return asctime(localtime(timep));
01207 }

char* ast_ctime_r ( time_t * const  timep,
char *  buf 
) const

Definition at line 1210 of file localtime.c.

01213 {
01214         struct tm tm;
01215 #ifdef SOLARIS
01216    return asctime_r(localtime_r(timep, &tm), buf, 256);
01217 #else
01218    return asctime_r(localtime_r(timep, &tm), buf);
01219 #endif
01220 }

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

Definition at line 1046 of file localtime.c.

References ast_mutex_lock(), ast_mutex_unlock(), ast_tzset(), and localsub().

01050 {
01051 #ifdef _THREAD_SAFE
01052    ast_mutex_lock(&lcl_mutex);
01053 #endif
01054    ast_tzset(zone);
01055    localsub(timep, 0L, p_tm, zone);
01056 #ifdef _THREAD_SAFE
01057    ast_mutex_unlock(&lcl_mutex);
01058 #endif
01059    return(p_tm);
01060 }

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

Definition at line 1490 of file localtime.c.

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

01493 {
01494    time_t mktime_return_value;
01495 #ifdef   _THREAD_SAFE
01496    ast_mutex_lock(&lcl_mutex);
01497 #endif
01498    ast_tzset(zone);
01499    mktime_return_value = time1(tmp, localsub, 0L, zone);
01500 #ifdef   _THREAD_SAFE
01501    ast_mutex_unlock(&lcl_mutex);
01502 #endif
01503    return(mktime_return_value);
01504 }

AST_MUTEX_DEFINE_STATIC ( gmt_mutex   ) 

AST_MUTEX_DEFINE_STATIC ( tzsetwall_mutex   ) 

AST_MUTEX_DEFINE_STATIC ( tzset_mutex   ) 

AST_MUTEX_DEFINE_STATIC ( lcl_mutex   ) 

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

Definition at line 227 of file localtime.c.

References result.

Referenced by tzload().

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

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

Given a pointer into a time zone string, extract a number from that string.

Returns:
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 407 of file localtime.c.

References is_digit.

Referenced by getrule(), and getsecs().

00408 {
00409    register char  c;
00410    register int   num;
00411 
00412    if (strp == NULL || !is_digit(c = *strp))
00413       return NULL;
00414    num = 0;
00415    do {
00416       num = num * 10 + (c - '0');
00417       if (num > max)
00418          return NULL;   /* illegal value */
00419       c = *++strp;
00420    } while (is_digit(c));
00421    if (num < min)
00422       return NULL;      /* illegal value */
00423    *nump = num;
00424    return strp;
00425 }

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

Given a pointer into a time zone string, extract an offset, in [+-]hh[:mm[:ss]] form, from the string.

Returns:
If any error occurs, return NULL. Otherwise, return a pointer to the first character not part of the time.

Definition at line 474 of file localtime.c.

References getsecs().

Referenced by tzparse().

00475 {
00476    register int   neg = 0;
00477 
00478    if (*strp == '-') {
00479       neg = 1;
00480       ++strp;
00481    } else if (*strp == '+')
00482       ++strp;
00483    strp = getsecs(strp, offsetp);
00484    if (strp == NULL)
00485       return NULL;      /* illegal time */
00486    if (neg)
00487       *offsetp = -*offsetp;
00488    return strp;
00489 }

static const char* getrule ( const char *  strp,
register struct rule *const   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".

Returns:
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 498 of file localtime.c.

References DAY_OF_YEAR, DAYSPERNYEAR, DAYSPERWEEK, getnum(), getsecs(), is_digit, JULIAN_DAY, MONSPERYEAR, MONTH_NTH_DAY_OF_WEEK, and SECSPERHOUR.

Referenced by tzparse().

00499 {
00500    if (*strp == 'J') {
00501       /*
00502       ** Julian day.
00503       */
00504       rulep->r_type = JULIAN_DAY;
00505       ++strp;
00506       strp = getnum(strp, &rulep->r_day, 1, DAYSPERNYEAR);
00507    } else if (*strp == 'M') {
00508       /*
00509       ** Month, week, day.
00510       */
00511       rulep->r_type = MONTH_NTH_DAY_OF_WEEK;
00512       ++strp;
00513       strp = getnum(strp, &rulep->r_mon, 1, MONSPERYEAR);
00514       if (strp == NULL)
00515          return NULL;
00516       if (*strp++ != '.')
00517          return NULL;
00518       strp = getnum(strp, &rulep->r_week, 1, 5);
00519       if (strp == NULL)
00520          return NULL;
00521       if (*strp++ != '.')
00522          return NULL;
00523       strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1);
00524    } else if (is_digit(*strp)) {
00525       /*
00526       ** Day of year.
00527       */
00528       rulep->r_type = DAY_OF_YEAR;
00529       strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1);
00530    } else   return NULL;      /* invalid format */
00531    if (strp == NULL)
00532       return NULL;
00533    if (*strp == '/') {
00534       /*
00535       ** Time specified.
00536       */
00537       ++strp;
00538       strp = getsecs(strp, &rulep->r_time);
00539    } else   rulep->r_time = 2 * SECSPERHOUR; /* default = 2:00:00 */
00540    return strp;
00541 }

static const char* getsecs ( register 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.

Returns:
If any error occurs, return NULL. Otherwise, return a pointer to the first character not part of the number of seconds.

Definition at line 435 of file localtime.c.

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

Referenced by getoffset(), and getrule().

00436 {
00437    int   num;
00438 
00439    /*
00440    ** `HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like
00441    ** "M10.4.6/26", which does not conform to Posix,
00442    ** but which specifies the equivalent of
00443    ** ``02:00 on the first Sunday on or after 23 Oct''.
00444    */
00445    strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1);
00446    if (strp == NULL)
00447       return NULL;
00448    *secsp = num * (long) SECSPERHOUR;
00449    if (*strp == ':') {
00450       ++strp;
00451       strp = getnum(strp, &num, 0, MINSPERHOUR - 1);
00452       if (strp == NULL)
00453          return NULL;
00454       *secsp += num * SECSPERMIN;
00455       if (*strp == ':') {
00456          ++strp;
00457          /* `SECSPERMIN' allows for leap seconds.  */
00458          strp = getnum(strp, &num, 0, SECSPERMIN);
00459          if (strp == NULL)
00460             return NULL;
00461          *secsp += num;
00462       }
00463    }
00464    return strp;
00465 }

static void gmtload ( struct state * const  sp  )  [static]

Definition at line 835 of file localtime.c.

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

Referenced by gmtsub(), and P().

00837 {
00838    if (tzload(gmt, sp) != 0)
00839       (void) tzparse(gmt, sp, TRUE);
00840 }

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

Definition at line 1067 of file localtime.c.

References ast_mutex_lock(), ast_mutex_unlock(), state::chars, gmt_is_set, gmtload(), gmtptr, malloc, timesub(), TRUE, and wildabbr.

Referenced by localsub().

01072 {
01073 #ifdef   _THREAD_SAFE
01074    ast_mutex_lock(&gmt_mutex);
01075 #endif
01076    if (!gmt_is_set) {
01077       gmt_is_set = TRUE;
01078       gmtptr = (struct state *) malloc(sizeof *gmtptr);
01079       if (gmtptr != NULL)
01080          gmtload(gmtptr);
01081    }
01082    ast_mutex_unlock(&gmt_mutex);
01083    timesub(timep, offset, gmtptr, tmp);
01084 #ifdef TM_ZONE
01085    /*
01086    ** Could get fancy here and deliver something such as
01087    ** "GMT+xxxx" or "GMT-xxxx" if offset is non-zero,
01088    ** but this is no time for a treasure hunt.
01089    */
01090    if (offset != 0)
01091       tmp->TM_ZONE = wildabbr;
01092    else {
01093       if (gmtptr == NULL)
01094          tmp->TM_ZONE = gmt;
01095       else  tmp->TM_ZONE = gmtptr->chars;
01096    }
01097 #endif /* defined TM_ZONE */
01098 }

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

Definition at line 1241 of file localtime.c.

Referenced by normalize_overflow(), and time2().

01244 {
01245    int   number0;
01246 
01247    number0 = *number;
01248    *number += delta;
01249    return (*number < number0) != (delta < 0);
01250 }

static void localsub ( time_t * const  timep,
const long  offset,
struct tm * const  tmp,
const char * const  zone 
) const [static]

Definition at line 979 of file localtime.c.

References ast_tzsetwall(), state::chars, gmtsub(), lclptr, state::name, state::next, t, state::timecnt, timesub(), ttinfo::tt_abbrind, ttinfo::tt_gmtoff, ttinfo::tt_isdst, state::ttis, state::typecnt, and state::types.

Referenced by ast_localtime(), ast_mktime(), and time1().

00984 {
00985    register struct state *    sp;
00986    register const struct ttinfo *   ttisp;
00987    register int         i;
00988    const time_t         t = *timep;
00989 
00990    sp = lclptr;
00991    /* Find the right zone record */
00992    if (zone == NULL)
00993       sp = NULL;
00994    else
00995       while (sp != NULL) {
00996          if (!strcmp(sp->name,zone))
00997             break;
00998          sp = sp->next;
00999       }
01000 
01001    if (sp == NULL) {
01002       ast_tzsetwall();
01003       sp = lclptr;
01004       /* Find the default zone record */
01005       while (sp != NULL) {
01006          if (sp->name[0] == '\0')
01007             break;
01008          sp = sp->next;
01009       }
01010    }
01011 
01012    /* Last ditch effort, use GMT */
01013    if (sp == NULL) {
01014       gmtsub(timep, offset, tmp, zone);
01015       return;
01016    }
01017    if (sp->timecnt == 0 || t < sp->ats[0]) {
01018       i = 0;
01019       while (sp->ttis[i].tt_isdst)
01020          if (++i >= sp->typecnt) {
01021             i = 0;
01022             break;
01023          }
01024    } else {
01025       for (i = 1; i < sp->timecnt; ++i)
01026          if (t < sp->ats[i])
01027             break;
01028       i = sp->types[i - 1];
01029    }
01030    ttisp = &sp->ttis[i];
01031    /*
01032    ** To get (wrong) behavior that's compatible with System V Release 2.0
01033    ** you'd replace the statement below with
01034    ** t += ttisp->tt_gmtoff;
01035    ** timesub(&t, 0L, sp, tmp);
01036    */
01037    timesub(&t, ttisp->tt_gmtoff, sp, tmp);
01038    tmp->tm_isdst = ttisp->tt_isdst;
01039    tzname[tmp->tm_isdst] = &sp->chars[ttisp->tt_abbrind];
01040 #ifdef TM_ZONE
01041    tmp->TM_ZONE = &sp->chars[ttisp->tt_abbrind];
01042 #endif /* defined TM_ZONE */
01043 }

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

Definition at line 1253 of file localtime.c.

References increment_overflow().

Referenced by time2().

01257 {
01258    register int   tensdelta;
01259 
01260    tensdelta = (*unitsptr >= 0) ?
01261       (*unitsptr / base) :
01262       (-1 - (-1 - *unitsptr) / base);
01263    *unitsptr -= tensdelta * base;
01264    return increment_overflow(tensptr, tensdelta);
01265 }

void ast_tzset P ( (const char *name  )  [static]

Definition at line 901 of file localtime.c.

References ast_tzsetwall(), FALSE, gmtload(), last_lclptr, lclptr, malloc, state::name, state::next, tzload(), and tzparse().

00906 {
00907    struct state *cur_state = lclptr;
00908 
00909    /* Not set at all */
00910    if (name == NULL) {
00911       return ast_tzsetwall();
00912    }
00913 
00914    /* Find the appropriate structure, if already parsed */
00915    while (cur_state != NULL) {
00916       if (!strcmp(cur_state->name,name))
00917          break;
00918       cur_state = cur_state->next;
00919    }
00920    if (cur_state != NULL)
00921       return 0;
00922 
00923    cur_state = malloc(sizeof(struct state));
00924    if (cur_state == NULL) {
00925       return -1;
00926    }
00927    memset(cur_state,0,sizeof(*cur_state));
00928 
00929    /* Name is set, but set to the empty string == no adjustments */
00930    if (name[0] == '\0') {
00931       /*
00932       ** User wants it fast rather than right.
00933       */
00934       cur_state->leapcnt = 0;    /* so, we're off a little */
00935       cur_state->timecnt = 0;
00936       cur_state->ttis[0].tt_gmtoff = 0;
00937       cur_state->ttis[0].tt_abbrind = 0;
00938       (void) strncpy(cur_state->chars, gmt, sizeof(cur_state->chars) - 1);
00939    } else if (tzload(name, cur_state) != 0) {
00940       if (name[0] == ':') {
00941          (void) gmtload(cur_state);
00942       } else if (tzparse(name, cur_state, FALSE) != 0) {
00943          /* If not found, load localtime */
00944          if (tzload("/etc/localtime", cur_state) != 0)
00945             /* Last ditch, get GMT */
00946             (void) gmtload(cur_state);
00947       }
00948    }
00949    strncpy(cur_state->name, name, sizeof(cur_state->name) - 1);
00950    if (last_lclptr)
00951       last_lclptr->next = cur_state;
00952    else
00953       lclptr = cur_state;
00954    last_lclptr = cur_state;
00955    return 0;
00956 }

int ast_tzsetwall P ( (void)   )  [static]

Definition at line 849 of file localtime.c.

References gmtload(), last_lclptr, lclptr, malloc, state::name, state::next, and tzload().

00854 {
00855    struct state *cur_state = lclptr;
00856 
00857    /* Find the appropriate structure, if already parsed */
00858    while (cur_state != NULL) {
00859       if (cur_state->name[0] == '\0')
00860          break;
00861       cur_state = cur_state->next;
00862    }
00863    if (cur_state != NULL)
00864       return 0;
00865    cur_state = malloc(sizeof(struct state));
00866    if (cur_state == NULL) {
00867       return -1;
00868    }
00869    memset(cur_state,0,sizeof(struct state));
00870    if (tzload((char *) NULL, cur_state) != 0)
00871 #ifdef DEBUG
00872    {
00873       fprintf(stderr, "ast_tzsetwall: calling gmtload()\n");
00874 #endif
00875       gmtload(cur_state);
00876 #ifdef DEBUG
00877    }
00878 #endif
00879 
00880    if (last_lclptr)
00881       last_lclptr->next = cur_state;
00882    else
00883       lclptr = cur_state;
00884    last_lclptr = cur_state;
00885    return 0;
00886 }

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

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

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

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

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

static time_t time2 P ( (struct tm *tmp, void(*funcp) P((const time_t *, long, struct tm *, const char *)), long offset, int *okayp, const char *zone)   )  [static]

static time_t time1 P ( (struct tm *tmp, void(*funcp) P((const time_t *, long, struct tm *, const char *)), long offset, const char *zone)   )  [static]

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

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

static void localsub P ( (const time_t *timep, long offset, struct tm *tmp, const char *zone)   )  [static]

static void 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 long detzcode P ( (const char *codep)   )  [static]

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

Definition at line 1429 of file localtime.c.

References gmtptr, lclptr, localsub(), t, time2(), ttinfo::tt_gmtoff, ttinfo::tt_isdst, state::ttis, and state::typecnt.

Referenced by ast_mktime().

01434 {
01435    register time_t         t;
01436    register const struct state * sp;
01437    register int         samei, otheri;
01438    int            okay;
01439 
01440    if (tmp->tm_isdst > 1)
01441       tmp->tm_isdst = 1;
01442    t = time2(tmp, funcp, offset, &okay, zone);
01443 #ifdef PCTS
01444    /*
01445    ** PCTS code courtesy Grant Sullivan (grant@osf.org).
01446    */
01447    if (okay)
01448       return t;
01449    if (tmp->tm_isdst < 0)
01450       tmp->tm_isdst = 0;   /* reset to std and try again */
01451 #endif /* defined PCTS */
01452 #ifndef PCTS
01453    if (okay || tmp->tm_isdst < 0)
01454       return t;
01455 #endif /* !defined PCTS */
01456    /*
01457    ** We're supposed to assume that somebody took a time of one type
01458    ** and did some math on it that yielded a "struct tm" that's bad.
01459    ** We try to divine the type they started from and adjust to the
01460    ** type they need.
01461    */
01462    /*
01463    ** The (void *) casts are the benefit of SunOS 3.3 on Sun 2's.
01464    */
01465    sp = (const struct state *) (((void *) funcp == (void *) localsub) ?
01466       lclptr : gmtptr);
01467    if (sp == NULL)
01468       return WRONG;
01469    for (samei = sp->typecnt - 1; samei >= 0; --samei) {
01470       if (sp->ttis[samei].tt_isdst != tmp->tm_isdst)
01471          continue;
01472       for (otheri = sp->typecnt - 1; otheri >= 0; --otheri) {
01473          if (sp->ttis[otheri].tt_isdst == tmp->tm_isdst)
01474             continue;
01475          tmp->tm_sec += sp->ttis[otheri].tt_gmtoff -
01476                sp->ttis[samei].tt_gmtoff;
01477          tmp->tm_isdst = !tmp->tm_isdst;
01478          t = time2(tmp, funcp, offset, &okay, zone);
01479          if (okay)
01480             return t;
01481          tmp->tm_sec -= sp->ttis[otheri].tt_gmtoff -
01482                sp->ttis[samei].tt_gmtoff;
01483          tmp->tm_isdst = !tmp->tm_isdst;
01484       }
01485    }
01486    return WRONG;
01487 }

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

Definition at line 1284 of file localtime.c.

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

Referenced by time1().

01290 {
01291    register const struct state * sp;
01292    register int         dir;
01293    register int         bits;
01294    register int         i, j ;
01295    register int         saved_seconds;
01296    time_t            newt;
01297    time_t            t;
01298    struct tm         yourtm, mytm;
01299 
01300    *okayp = FALSE;
01301    yourtm = *tmp;
01302    if (normalize_overflow(&yourtm.tm_hour, &yourtm.tm_min, MINSPERHOUR))
01303       return WRONG;
01304    if (normalize_overflow(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY))
01305       return WRONG;
01306    if (normalize_overflow(&yourtm.tm_year, &yourtm.tm_mon, MONSPERYEAR))
01307       return WRONG;
01308    /*
01309    ** Turn yourtm.tm_year into an actual year number for now.
01310    ** It is converted back to an offset from TM_YEAR_BASE later.
01311    */
01312    if (increment_overflow(&yourtm.tm_year, TM_YEAR_BASE))
01313       return WRONG;
01314    while (yourtm.tm_mday <= 0) {
01315       if (increment_overflow(&yourtm.tm_year, -1))
01316          return WRONG;
01317       i = yourtm.tm_year + (1 < yourtm.tm_mon);
01318       yourtm.tm_mday += year_lengths[isleap(i)];
01319    }
01320    while (yourtm.tm_mday > DAYSPERLYEAR) {
01321       i = yourtm.tm_year + (1 < yourtm.tm_mon);
01322       yourtm.tm_mday -= year_lengths[isleap(i)];
01323       if (increment_overflow(&yourtm.tm_year, 1))
01324          return WRONG;
01325    }
01326    for ( ; ; ) {
01327       i = mon_lengths[isleap(yourtm.tm_year)][yourtm.tm_mon];
01328       if (yourtm.tm_mday <= i)
01329          break;
01330       yourtm.tm_mday -= i;
01331       if (++yourtm.tm_mon >= MONSPERYEAR) {
01332          yourtm.tm_mon = 0;
01333          if (increment_overflow(&yourtm.tm_year, 1))
01334             return WRONG;
01335       }
01336    }
01337    if (increment_overflow(&yourtm.tm_year, -TM_YEAR_BASE))
01338       return WRONG;
01339    if (yourtm.tm_year + TM_YEAR_BASE < EPOCH_YEAR) {
01340       /*
01341       ** We can't set tm_sec to 0, because that might push the
01342       ** time below the minimum representable time.
01343       ** Set tm_sec to 59 instead.
01344       ** This assumes that the minimum representable time is
01345       ** not in the same minute that a leap second was deleted from,
01346       ** which is a safer assumption than using 58 would be.
01347       */
01348       if (increment_overflow(&yourtm.tm_sec, 1 - SECSPERMIN))
01349          return WRONG;
01350       saved_seconds = yourtm.tm_sec;
01351       yourtm.tm_sec = SECSPERMIN - 1;
01352    } else {
01353       saved_seconds = yourtm.tm_sec;
01354       yourtm.tm_sec = 0;
01355    }
01356    /*
01357    ** Divide the search space in half
01358    ** (this works whether time_t is signed or unsigned).
01359    */
01360    bits = TYPE_BIT(time_t) - 1;
01361    /*
01362    ** If time_t is signed, then 0 is just above the median,
01363    ** assuming two's complement arithmetic.
01364    ** If time_t is unsigned, then (1 << bits) is just above the median.
01365    */
01366    t = TYPE_SIGNED(time_t) ? 0 : (((time_t) 1) << bits);
01367    for ( ; ; ) {
01368       (*funcp)(&t, offset, &mytm, zone);
01369       dir = tmcomp(&mytm, &yourtm);
01370       if (dir != 0) {
01371          if (bits-- < 0)
01372             return WRONG;
01373          if (bits < 0)
01374             --t; /* may be needed if new t is minimal */
01375          else if (dir > 0)
01376             t -= ((time_t) 1) << bits;
01377          else  t += ((time_t) 1) << bits;
01378          continue;
01379       }
01380       if (yourtm.tm_isdst < 0 || mytm.tm_isdst == yourtm.tm_isdst)
01381          break;
01382       /*
01383       ** Right time, wrong type.
01384       ** Hunt for right time, right type.
01385       ** It's okay to guess wrong since the guess
01386       ** gets checked.
01387       */
01388       /*
01389       ** The (void *) casts are the benefit of SunOS 3.3 on Sun 2's.
01390       */
01391       sp = (const struct state *)
01392          (((void *) funcp == (void *) localsub) ?
01393          lclptr : gmtptr);
01394       if (sp == NULL)
01395          return WRONG;
01396       for (i = sp->typecnt - 1; i >= 0; --i) {
01397          if (sp->ttis[i].tt_isdst != yourtm.tm_isdst)
01398             continue;
01399          for (j = sp->typecnt - 1; j >= 0; --j) {
01400             if (sp->ttis[j].tt_isdst == yourtm.tm_isdst)
01401                continue;
01402             newt = t + sp->ttis[j].tt_gmtoff -
01403                sp->ttis[i].tt_gmtoff;
01404             (*funcp)(&newt, offset, &mytm, zone);
01405             if (tmcomp(&mytm, &yourtm) != 0)
01406                continue;
01407             if (mytm.tm_isdst != yourtm.tm_isdst)
01408                continue;
01409             /*
01410             ** We have a match.
01411             */
01412             t = newt;
01413             goto label;
01414          }
01415       }
01416       return WRONG;
01417    }
01418 label:
01419    newt = t + saved_seconds;
01420    if ((newt < t) != (saved_seconds < 0))
01421       return WRONG;
01422    t = newt;
01423    (*funcp)(&t, offset, tmp, zone);
01424    *okayp = TRUE;
01425    return t;
01426 }

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

Definition at line 1101 of file localtime.c.

References days, DAYSPERNYEAR, DAYSPERWEEK, EPOCH_WDAY, EPOCH_YEAR, isleap, LEAPS_THRU_END_OF, lsinfo::ls_corr, lsinfo::ls_trans, mon_lengths, SECSPERDAY, SECSPERHOUR, SECSPERMIN, TM_YEAR_BASE, and year_lengths.

Referenced by gmtsub(), and localsub().

01106 {
01107    register const struct lsinfo *   lp;
01108    register long        days;
01109    register long        rem;
01110    register int         y;
01111    register int         yleap;
01112    register const int *    ip;
01113    register long        corr;
01114    register int         hit;
01115    register int         i;
01116 
01117    corr = 0;
01118    hit = 0;
01119    i = (sp == NULL) ? 0 : sp->leapcnt;
01120    while (--i >= 0) {
01121       lp = &sp->lsis[i];
01122       if (*timep >= lp->ls_trans) {
01123          if (*timep == lp->ls_trans) {
01124             hit = ((i == 0 && lp->ls_corr > 0) ||
01125                lp->ls_corr > sp->lsis[i - 1].ls_corr);
01126             if (hit)
01127                while (i > 0 &&
01128                   sp->lsis[i].ls_trans ==
01129                   sp->lsis[i - 1].ls_trans + 1 &&
01130                   sp->lsis[i].ls_corr ==
01131                   sp->lsis[i - 1].ls_corr + 1) {
01132                      ++hit;
01133                      --i;
01134                }
01135          }
01136          corr = lp->ls_corr;
01137          break;
01138       }
01139    }
01140    days = *timep / SECSPERDAY;
01141    rem = *timep % SECSPERDAY;
01142 #ifdef mc68k
01143    if (*timep == 0x80000000) {
01144       /*
01145       ** A 3B1 muffs the division on the most negative number.
01146       */
01147       days = -24855;
01148       rem = -11648;
01149    }
01150 #endif /* defined mc68k */
01151    rem += (offset - corr);
01152    while (rem < 0) {
01153       rem += SECSPERDAY;
01154       --days;
01155    }
01156    while (rem >= SECSPERDAY) {
01157       rem -= SECSPERDAY;
01158       ++days;
01159    }
01160    tmp->tm_hour = (int) (rem / SECSPERHOUR);
01161    rem = rem % SECSPERHOUR;
01162    tmp->tm_min = (int) (rem / SECSPERMIN);
01163    /*
01164    ** A positive leap second requires a special
01165    ** representation.  This uses "... ??:59:60" et seq.
01166    */
01167    tmp->tm_sec = (int) (rem % SECSPERMIN) + hit;
01168    tmp->tm_wday = (int) ((EPOCH_WDAY + days) % DAYSPERWEEK);
01169    if (tmp->tm_wday < 0)
01170       tmp->tm_wday += DAYSPERWEEK;
01171    y = EPOCH_YEAR;
01172 #define LEAPS_THRU_END_OF(y)  ((y) / 4 - (y) / 100 + (y) / 400)
01173    while (days < 0 || days >= (long) year_lengths[yleap = isleap(y)]) {
01174       register int   newy;
01175 
01176       newy = y + days / DAYSPERNYEAR;
01177       if (days < 0)
01178          --newy;
01179       days -= (newy - y) * DAYSPERNYEAR +
01180          LEAPS_THRU_END_OF(newy - 1) -
01181          LEAPS_THRU_END_OF(y - 1);
01182       y = newy;
01183    }
01184    tmp->tm_year = y - TM_YEAR_BASE;
01185    tmp->tm_yday = (int) days;
01186    ip = mon_lengths[yleap];
01187    for (tmp->tm_mon = 0; days >= (long) ip[tmp->tm_mon]; ++(tmp->tm_mon))
01188       days = days - (long) ip[tmp->tm_mon];
01189    tmp->tm_mday = (int) (days + 1);
01190    tmp->tm_isdst = 0;
01191 #ifdef TM_GMTOFF
01192    tmp->TM_GMTOFF = offset;
01193 #endif /* defined TM_GMTOFF */
01194 }

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

Definition at line 1268 of file localtime.c.

References result.

01271 {
01272    register int   result;
01273 
01274    if ((result = (atmp->tm_year - btmp->tm_year)) == 0 &&
01275       (result = (atmp->tm_mon - btmp->tm_mon)) == 0 &&
01276       (result = (atmp->tm_mday - btmp->tm_mday)) == 0 &&
01277       (result = (atmp->tm_hour - btmp->tm_hour)) == 0 &&
01278       (result = (atmp->tm_min - btmp->tm_min)) == 0)
01279          result = atmp->tm_sec - btmp->tm_sec;
01280    return result;
01281 }

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

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

Definition at line 549 of file localtime.c.

References DAY_OF_YEAR, DAYSPERWEEK, isleap, JULIAN_DAY, m1, MONTH_NTH_DAY_OF_WEEK, and SECSPERDAY.

Referenced by tzparse().

00554 {
00555    register int   leapyear;
00556    register time_t   value = 0;
00557    register int   i;
00558    int      d, m1, yy0, yy1, yy2, dow;
00559 
00560    leapyear = isleap(year);
00561    switch (rulep->r_type) {
00562 
00563    case JULIAN_DAY:
00564       /*
00565       ** Jn - Julian day, 1 == January 1, 60 == March 1 even in leap
00566       ** years.
00567       ** In non-leap years, or if the day number is 59 or less, just
00568       ** add SECSPERDAY times the day number-1 to the time of
00569       ** January 1, midnight, to get the day.
00570       */
00571       value = janfirst + (rulep->r_day - 1) * SECSPERDAY;
00572       if (leapyear && rulep->r_day >= 60)
00573          value += SECSPERDAY;
00574       break;
00575 
00576    case DAY_OF_YEAR:
00577       /*
00578       ** n - day of year.
00579       ** Just add SECSPERDAY times the day number to the time of
00580       ** January 1, midnight, to get the day.
00581       */
00582       value = janfirst + rulep->r_day * SECSPERDAY;
00583       break;
00584 
00585    case MONTH_NTH_DAY_OF_WEEK:
00586       /*
00587       ** Mm.n.d - nth "dth day" of month m.
00588       */
00589       value = janfirst;
00590       for (i = 0; i < rulep->r_mon - 1; ++i)
00591          value += mon_lengths[leapyear][i] * SECSPERDAY;
00592 
00593       /*
00594       ** Use Zeller's Congruence to get day-of-week of first day of
00595       ** month.
00596       */
00597       m1 = (rulep->r_mon + 9) % 12 + 1;
00598       yy0 = (rulep->r_mon <= 2) ? (year - 1) : year;
00599       yy1 = yy0 / 100;
00600       yy2 = yy0 % 100;
00601       dow = ((26 * m1 - 2) / 10 +
00602          1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7;
00603       if (dow < 0)
00604          dow += DAYSPERWEEK;
00605 
00606       /*
00607       ** "dow" is the day-of-week of the first day of the month.  Get
00608       ** the day-of-month (zero-origin) of the first "dow" day of the
00609       ** month.
00610       */
00611       d = rulep->r_day - dow;
00612       if (d < 0)
00613          d += DAYSPERWEEK;
00614       for (i = 1; i < rulep->r_week; ++i) {
00615          if (d + DAYSPERWEEK >=
00616             mon_lengths[leapyear][rulep->r_mon - 1])
00617                break;
00618          d += DAYSPERWEEK;
00619       }
00620 
00621       /*
00622       ** "d" is the day-of-month (zero-origin) of the day we want.
00623       */
00624       value += d * SECSPERDAY;
00625       break;
00626    }
00627 
00628    /*
00629    ** "value" is the Epoch-relative time of 00:00:00 GMT on the day in
00630    ** question.  To get the Epoch-relative time of the specified local
00631    ** time on that day, add the transition time and the current offset
00632    ** from GMT.
00633    */
00634    return value + rulep->r_time + offset;
00635 }

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

Definition at line 238 of file localtime.c.

References detzcode(), FALSE, FILENAME_MAX, OPEN_MODE, TRUE, TZ_MAX_CHARS, TZ_MAX_LEAPS, TZ_MAX_TIMES, TZ_MAX_TYPES, TZDEFAULT, TZDIR, tzhead::tzh_magic, and tzhead::tzh_reserved.

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

00239 {
00240    register const char *   p;
00241    register int      i;
00242    register int      fid;
00243 
00244 #ifdef DEBUG
00245    fprintf(stderr,"tzload called with name=%s, sp=%d\n", name, sp);
00246 #endif
00247    if (name == NULL && (name = TZDEFAULT) == NULL)
00248       return -1;
00249    {
00250       register int   doaccess;
00251       struct stat stab;
00252       /*
00253       ** Section 4.9.1 of the C standard says that
00254       ** "FILENAME_MAX expands to an integral constant expression
00255       ** that is the size needed for an array of char large enough
00256       ** to hold the longest file name string that the implementation
00257       ** guarantees can be opened."
00258       */
00259       char     fullname[FILENAME_MAX + 1] = "";
00260 
00261       if (name[0] == ':')
00262          ++name;
00263       doaccess = name[0] == '/';
00264       if (!doaccess) {
00265          if ((p = TZDIR) == NULL)
00266             return -1;
00267          if ((strlen(p) + 1 + strlen(name) + 1) >= sizeof fullname)
00268             return -1;
00269          (void) strncpy(fullname, p, sizeof(fullname) - 1);
00270          (void) strncat(fullname, "/", sizeof(fullname) - strlen(fullname) - 1);
00271          (void) strncat(fullname, name, sizeof(fullname) - strlen(fullname) - 1);
00272          /*
00273          ** Set doaccess if '.' (as in "../") shows up in name.
00274          */
00275          if (strchr(name, '.') != NULL)
00276             doaccess = TRUE;
00277          name = fullname;
00278       }
00279       if (doaccess && access(name, R_OK) != 0)
00280             return -1;
00281       if ((fid = open(name, OPEN_MODE)) == -1)
00282          return -1;
00283       if ((fstat(fid, &stab) < 0) || !S_ISREG(stab.st_mode)) {
00284          close(fid);
00285          return -1;
00286       }
00287    }
00288    {
00289       struct tzhead *   tzhp;
00290       char     buf[sizeof *sp + sizeof *tzhp];
00291       int      ttisstdcnt;
00292       int      ttisgmtcnt;
00293 
00294       i = read(fid, buf, sizeof buf);
00295       if (close(fid) != 0)
00296          return -1;
00297       p = buf;
00298       p += (sizeof tzhp->tzh_magic) + (sizeof tzhp->tzh_reserved);
00299       ttisstdcnt = (int) detzcode(p);
00300       p += 4;
00301       ttisgmtcnt = (int) detzcode(p);
00302       p += 4;
00303       sp->leapcnt = (int) detzcode(p);
00304       p += 4;
00305       sp->timecnt = (int) detzcode(p);
00306       p += 4;
00307       sp->typecnt = (int) detzcode(p);
00308       p += 4;
00309       sp->charcnt = (int) detzcode(p);
00310       p += 4;
00311       if (sp->leapcnt < 0 || sp->leapcnt > TZ_MAX_LEAPS ||
00312          sp->typecnt <= 0 || sp->typecnt > TZ_MAX_TYPES ||
00313          sp->timecnt < 0 || sp->timecnt > TZ_MAX_TIMES ||
00314          sp->charcnt < 0 || sp->charcnt > TZ_MAX_CHARS ||
00315          (ttisstdcnt != sp->typecnt && ttisstdcnt != 0) ||
00316          (ttisgmtcnt != sp->typecnt && ttisgmtcnt != 0))
00317             return -1;
00318       if (i - (p - buf) < sp->timecnt * 4 +  /* ats */
00319          sp->timecnt +        /* types */
00320          sp->typecnt * (4 + 2) +    /* ttinfos */
00321          sp->charcnt +        /* chars */
00322          sp->leapcnt * (4 + 4) +    /* lsinfos */
00323          ttisstdcnt +         /* ttisstds */
00324          ttisgmtcnt)       /* ttisgmts */
00325             return -1;
00326       for (i = 0; i < sp->timecnt; ++i) {
00327          sp->ats[i] = detzcode(p);
00328          p += 4;
00329       }
00330       for (i = 0; i < sp->timecnt; ++i) {
00331          sp->types[i] = (unsigned char) *p++;
00332          if (sp->types[i] >= sp->typecnt)
00333             return -1;
00334       }
00335       for (i = 0; i < sp->typecnt; ++i) {
00336          register struct ttinfo *   ttisp;
00337 
00338          ttisp = &sp->ttis[i];
00339          ttisp->tt_gmtoff = detzcode(p);
00340          p += 4;
00341          ttisp->tt_isdst = (unsigned char) *p++;
00342          if (ttisp->tt_isdst != 0 && ttisp->tt_isdst != 1)
00343             return -1;
00344          ttisp->tt_abbrind = (unsigned char) *p++;
00345          if (ttisp->tt_abbrind < 0 ||
00346             ttisp->tt_abbrind > sp->charcnt)
00347                return -1;
00348       }
00349       for (i = 0; i < sp->charcnt; ++i)
00350          sp->chars[i] = *p++;
00351       sp->chars[i] = '\0'; /* ensure '\0' at end */
00352       for (i = 0; i < sp->leapcnt; ++i) {
00353          register struct lsinfo *   lsisp;
00354 
00355          lsisp = &sp->lsis[i];
00356          lsisp->ls_trans = detzcode(p);
00357          p += 4;
00358          lsisp->ls_corr = detzcode(p);
00359          p += 4;
00360       }
00361       for (i = 0; i < sp->typecnt; ++i) {
00362          register struct ttinfo *   ttisp;
00363 
00364          ttisp = &sp->ttis[i];
00365          if (ttisstdcnt == 0)
00366             ttisp->tt_ttisstd = FALSE;
00367          else {
00368             ttisp->tt_ttisstd = *p++;
00369             if (ttisp->tt_ttisstd != TRUE &&
00370                ttisp->tt_ttisstd != FALSE)
00371                   return -1;
00372          }
00373       }
00374       for (i = 0; i < sp->typecnt; ++i) {
00375          register struct ttinfo *   ttisp;
00376 
00377          ttisp = &sp->ttis[i];
00378          if (ttisgmtcnt == 0)
00379             ttisp->tt_ttisgmt = FALSE;
00380          else {
00381             ttisp->tt_ttisgmt = *p++;
00382             if (ttisp->tt_ttisgmt != TRUE &&
00383                ttisp->tt_ttisgmt != FALSE)
00384                   return -1;
00385          }
00386       }
00387    }
00388    return 0;
00389 }

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

Definition at line 643 of file localtime.c.

References EPOCH_YEAR, FALSE, getoffset(), getrule(), isleap, SECSPERDAY, SECSPERHOUR, transtime(), TZ_MAX_TIMES, TZDEFRULES, and tzload().

Referenced by gmtload(), and P().

00647 {
00648    const char *         stdname;
00649    const char *         dstname = NULL;
00650    size_t            stdlen = 0;
00651    size_t            dstlen = 0;
00652    long           stdoffset = 0L;
00653    long           dstoffset = 0L;
00654    register time_t *    atp;
00655    register unsigned char *   typep;
00656    register char *         cp;
00657    register int         load_result;
00658 
00659    stdname = name;
00660 #ifdef DEBUG
00661    fprintf(stderr, "tzparse(): loading default rules\n");
00662 #endif
00663    load_result = tzload(TZDEFRULES, sp);
00664    if (load_result != 0)
00665       sp->leapcnt = 0;     /* so, we're off a little */
00666    if (*name != '\0') {
00667       if (*name != '\0' && *name != ',' && *name != ';') {
00668          name = getoffset(name, &dstoffset);
00669          if (name == NULL)
00670             return -1;
00671       } else   dstoffset = stdoffset - SECSPERHOUR;
00672       if (*name == ',' || *name == ';') {
00673          struct rule start;
00674          struct rule end;
00675          register int   year;
00676          register time_t   janfirst;
00677          time_t      starttime;
00678          time_t      endtime;
00679 
00680          ++name;
00681          if ((name = getrule(name, &start)) == NULL)
00682             return -1;
00683          if (*name++ != ',')
00684             return -1;
00685          if ((name = getrule(name, &end)) == NULL)
00686             return -1;
00687          if (*name != '\0')
00688             return -1;
00689          sp->typecnt = 2;  /* standard time and DST */
00690          /*
00691          ** Two transitions per year, from EPOCH_YEAR to 2037.
00692          */
00693          sp->timecnt = 2 * (2037 - EPOCH_YEAR + 1);
00694          if (sp->timecnt > TZ_MAX_TIMES)
00695             return -1;
00696          sp->ttis[0].tt_gmtoff = -dstoffset;
00697          sp->ttis[0].tt_isdst = 1;
00698          sp->ttis[0].tt_abbrind = stdlen + 1;
00699          sp->ttis[1].tt_gmtoff = -stdoffset;
00700          sp->ttis[1].tt_isdst = 0;
00701          sp->ttis[1].tt_abbrind = 0;
00702          atp = sp->ats;
00703          typep = sp->types;
00704          janfirst = 0;
00705          for (year = EPOCH_YEAR; year <= 2037; ++year) {
00706             starttime = transtime(janfirst, year, &start,
00707                stdoffset);
00708             endtime = transtime(janfirst, year, &end,
00709                dstoffset);
00710             if (starttime > endtime) {
00711                *atp++ = endtime;
00712                *typep++ = 1;  /* DST ends */
00713                *atp++ = starttime;
00714                *typep++ = 0;  /* DST begins */
00715             } else {
00716                *atp++ = starttime;
00717                *typep++ = 0;  /* DST begins */
00718                *atp++ = endtime;
00719                *typep++ = 1;  /* DST ends */
00720             }
00721             janfirst += year_lengths[isleap(year)] *
00722                SECSPERDAY;
00723          }
00724       } else {
00725          register long  theirstdoffset;
00726          register long  theirdstoffset;
00727          register long  theiroffset;
00728          register int   isdst;
00729          register int   i;
00730          register int   j;
00731 
00732          if (*name != '\0')
00733             return -1;
00734          if (load_result != 0)
00735             return -1;
00736          /*
00737          ** Initial values of theirstdoffset and theirdstoffset.
00738          */
00739          theirstdoffset = 0;
00740          for (i = 0; i < sp->timecnt; ++i) {
00741             j = sp->types[i];
00742             if (!sp->ttis[j].tt_isdst) {
00743                theirstdoffset =
00744                   -sp->ttis[j].tt_gmtoff;
00745                break;
00746             }
00747          }
00748          theirdstoffset = 0;
00749          for (i = 0; i < sp->timecnt; ++i) {
00750             j = sp->types[i];
00751             if (sp->ttis[j].tt_isdst) {
00752                theirdstoffset =
00753                   -sp->ttis[j].tt_gmtoff;
00754                break;
00755             }
00756          }
00757          /*
00758          ** Initially we're assumed to be in standard time.
00759          */
00760          isdst = FALSE;
00761          theiroffset = theirstdoffset;
00762          /*
00763          ** Now juggle transition times and types
00764          ** tracking offsets as you do.
00765          */
00766          for (i = 0; i < sp->timecnt; ++i) {
00767             j = sp->types[i];
00768             sp->types[i] = sp->ttis[j].tt_isdst;
00769             if (sp->ttis[j].tt_ttisgmt) {
00770                /* No adjustment to transition time */
00771             } else {
00772                /*
00773                ** If summer time is in effect, and the
00774                ** transition time was not specified as
00775                ** standard time, add the summer time
00776                ** offset to the transition time;
00777                ** otherwise, add the standard time
00778                ** offset to the transition time.
00779                */
00780                /*
00781                ** Transitions from DST to DDST
00782                ** will effectively disappear since
00783                ** POSIX provides for only one DST
00784                ** offset.
00785                */
00786                if (isdst && !sp->ttis[j].tt_ttisstd) {
00787                   sp->ats[i] += dstoffset -
00788                      theirdstoffset;
00789                } else {
00790                   sp->ats[i] += stdoffset -
00791                      theirstdoffset;
00792                }
00793             }
00794             theiroffset = -sp->ttis[j].tt_gmtoff;
00795             if (sp->ttis[j].tt_isdst)
00796                theirdstoffset = theiroffset;
00797             else  theirstdoffset = theiroffset;
00798          }
00799          /*
00800          ** Finally, fill in ttis.
00801          ** ttisstd and ttisgmt need not be handled.
00802          */
00803          sp->ttis[0].tt_gmtoff = -stdoffset;
00804          sp->ttis[0].tt_isdst = FALSE;
00805          sp->ttis[0].tt_abbrind = 0;
00806          sp->ttis[1].tt_gmtoff = -dstoffset;
00807          sp->ttis[1].tt_isdst = TRUE;
00808          sp->ttis[1].tt_abbrind = stdlen + 1;
00809       }
00810    } else {
00811       dstlen = 0;
00812       sp->typecnt = 1;     /* only standard time */
00813       sp->timecnt = 0;
00814       sp->ttis[0].tt_gmtoff = -stdoffset;
00815       sp->ttis[0].tt_isdst = 0;
00816       sp->ttis[0].tt_abbrind = 0;
00817    }
00818    sp->charcnt = stdlen + 1;
00819    if (dstlen != 0)
00820       sp->charcnt += dstlen + 1;
00821    if (sp->charcnt > sizeof sp->chars)
00822       return -1;
00823    cp = sp->chars;
00824    (void) strncpy(cp, stdname, stdlen);
00825    cp += stdlen;
00826    *cp++ = '\0';
00827    if (dstlen != 0) {
00828       (void) strncpy(cp, dstname, dstlen);
00829       *(cp + dstlen) = '\0';
00830    }
00831    return 0;
00832 }


Variable Documentation

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

Definition at line 63 of file localtime.c.

char gmt[] = "GMT" [static]

FreeBSD defines 'zone' in 'struct tm' as non-const, so don't declare this string as const. time type information.

Definition at line 114 of file localtime.c.

int gmt_is_set [static]

Definition at line 211 of file localtime.c.

Referenced by gmtsub().

struct state* gmtptr = NULL [static]

Definition at line 205 of file localtime.c.

Referenced by gmtsub(), and time1().

struct state* last_lclptr = NULL [static]

Definition at line 204 of file localtime.c.

Referenced by P().

struct state* lclptr = NULL [static]

Definition at line 203 of file localtime.c.

Referenced by localsub(), P(), and time1().

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

Referenced by time2(), and timesub().

char wildabbr[] = "WILDABBR" [static]

Definition at line 109 of file localtime.c.

Referenced by gmtsub().

const int year_lengths[2] [static]

Initial value:

Definition at line 396 of file localtime.c.

Referenced by time2(), and timesub().


Generated on Mon Sep 18 09:15:15 2006 for Asterisk - the Open Source PBX by  doxygen 1.4.7