Mon May 14 04:50:28 2007

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.h"
#include "asterisk/lock.h"
#include "asterisk/localtime.h"
#include "asterisk/strings.h"

Include dependency graph for localtime.c:

This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

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

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

#define DAY_OF_YEAR   1

n - day of year

Definition at line 169 of file localtime.c.

Referenced by getrule(), and transtime().

#define JULIAN_DAY   0

Jn - Julian day

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

Referenced by getrule(), and transtime().

#define MY_TZNAME_MAX   255

Definition at line 142 of file localtime.c.

#define OPEN_MODE   O_RDONLY

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

#define WRONG   (-1)

Definition at line 1234 of file localtime.c.

Referenced by time2().


Function Documentation

char* ast_ctime ( time_t * const  timep  )  const

Definition at line 1202 of file localtime.c.

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

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

Definition at line 1215 of file localtime.c.

01218 {
01219         struct tm tm;
01220    return asctime_r(localtime_r(timep, &tm), buf);
01221 }

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

Definition at line 1051 of file localtime.c.

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

01055 {
01056 #ifdef _THREAD_SAFE
01057    ast_mutex_lock(&lcl_mutex);
01058 #endif
01059    ast_tzset(ast_strlen_zero(zone) ? "/etc/localtime" : zone);
01060    localsub(timep, 0L, p_tm, zone);
01061 #ifdef _THREAD_SAFE
01062    ast_mutex_unlock(&lcl_mutex);
01063 #endif
01064    return(p_tm);
01065 }

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

Definition at line 1491 of file localtime.c.

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

Referenced by acf_strptime().

01494 {
01495    time_t mktime_return_value;
01496 #ifdef   _THREAD_SAFE
01497    ast_mutex_lock(&lcl_mutex);
01498 #endif
01499    ast_tzset(!ast_strlen_zero(zone) ? zone : "/etc/localtime");
01500    mktime_return_value = time1(tmp, localsub, 0L, !ast_strlen_zero(zone) ? zone : "/etc/localtime");
01501 #ifdef   _THREAD_SAFE
01502    ast_mutex_unlock(&lcl_mutex);
01503 #endif
01504    return(mktime_return_value);
01505 }

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

References result.

Referenced by tzload().

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

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

References is_digit.

Referenced by getrule(), and getsecs().

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

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

References getsecs().

Referenced by tzparse().

00480 {
00481    register int   neg = 0;
00482 
00483    if (*strp == '-') {
00484       neg = 1;
00485       ++strp;
00486    } else if (*strp == '+')
00487       ++strp;
00488    strp = getsecs(strp, offsetp);
00489    if (strp == NULL)
00490       return NULL;      /* illegal time */
00491    if (neg)
00492       *offsetp = -*offsetp;
00493    return strp;
00494 }

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

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

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

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

Referenced by getoffset(), and getrule().

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

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

Definition at line 840 of file localtime.c.

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

Referenced by gmtsub(), and P().

00842 {
00843    if (tzload(gmt, sp) != 0)
00844       (void) tzparse(gmt, sp, TRUE);
00845 }

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

Definition at line 1072 of file localtime.c.

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

Referenced by localsub().

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

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

Definition at line 1242 of file localtime.c.

Referenced by normalize_overflow(), and time2().

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

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

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

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

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

Definition at line 1254 of file localtime.c.

References increment_overflow().

Referenced by time2().

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

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

Definition at line 906 of file localtime.c.

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

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

int ast_tzsetwall P ( (void)   )  [static]

Definition at line 854 of file localtime.c.

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

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

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

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

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

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

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

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

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

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

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

Definition at line 1269 of file localtime.c.

References result.

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

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

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

Referenced by tzparse().

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

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

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

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

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

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

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


Variable Documentation

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

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

int gmt_is_set [static]

Definition at line 216 of file localtime.c.

Referenced by gmtsub().

struct state* gmtptr = NULL [static]

Definition at line 210 of file localtime.c.

Referenced by gmtsub(), and time1().

struct state* last_lclptr = NULL [static]

Definition at line 209 of file localtime.c.

Referenced by P().

struct state* lclptr = NULL [static]

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

Referenced by time2(), and timesub().

char wildabbr[] = "WILDABBR" [static]

Definition at line 114 of file localtime.c.

const int year_lengths[2] [static]

Initial value:

Definition at line 401 of file localtime.c.

Referenced by time2(), and timesub().


Generated on Mon May 14 04:50:30 2007 for Asterisk - the Open Source PBX by  doxygen 1.5.1