Asterisk.org: Developer Documentation (28 Oct 2009)

Wed Oct 28 15:49:03 2009

## 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"`
`#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
struct 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.
static int | gmt_is_set
static struct state * | gmtptr = NULL
static struct state * | last_lclptr = NULL
static struct state * | lclptr = 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,
|  | b |  | ) | (((a) > (b)) ? (a) : (b))

Definition at line 132 of file localtime.c.

#define DAY_OF_YEAR 1

n - day of year

Definition at line 165 of file localtime.c.

Referenced by getrule(), and transtime().

#define JULIAN_DAY 0

Jn - Julian day

Definition at line 164 of file localtime.c.

Referenced by getrule(), and transtime().

#define LEAPS_THRU_END_OF | ( | y |  | ) | ((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 166 of file localtime.c.

Referenced by getrule(), and transtime().

#define MY_TZNAME_MAX 255

Definition at line 138 of file localtime.c.

#define OPEN_MODE O_RDONLY

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

#define WRONG (-1)

Definition at line 1234 of file localtime.c.

Referenced by time1(), and time2().

## Function Documentation

char* ast_ctime | ( | time_t * const | timep | ) | const

Definition at line 1198 of file localtime.c.

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

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

Definition at line 1211 of file localtime.c.

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

struct tm* ast_localtime | ( | time_t * const | timep,
|  | struct tm * | p_tm,
|  | const char * const | zone |
| ) |  |  | const`[read]`

Definition at line 1047 of file localtime.c.

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

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

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

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

References result.

Referenced by tzload().

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

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

References is_digit.

Referenced by getrule(), and getsecs().

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

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

References getsecs().

Referenced by tzparse().

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

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

References DAY_OF_YEAR, DAYSPERLYEAR, DAYSPERNYEAR, DAYSPERWEEK, getnum(), getsecs(), is_digit, JULIAN_DAY, MONSPERYEAR, MONTH_NTH_DAY_OF_WEEK, rule::r_day, rule::r_mon, rule::r_time, rule::r_type, rule::r_week, and SECSPERHOUR.

Referenced by tzparse().

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

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

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

Referenced by getoffset(), and getrule().

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

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

Definition at line 836 of file localtime.c.

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

Referenced by gmtsub(), and P().

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

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

Definition at line 1068 of file localtime.c.

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

Referenced by localsub().

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

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

References ast_tzsetwall(), state::chars, gmtsub(), 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(), time1(), and time2().

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

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

References ast_tzsetwall(), state::chars, FALSE, gmt, gmtload(), state::leapcnt, malloc, state::name, state::next, state::timecnt, ttinfo::tt_abbrind, ttinfo::tt_gmtoff, state::ttis, tzload(), and tzparse().

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

int ast_tzsetwall P | ( | (void) |  | ) | `[static]`

Definition at line 850 of file localtime.c.

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

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

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 localsub(), t, time2(), ttinfo::tt_gmtoff, ttinfo::tt_isdst, state::ttis, state::typecnt, and WRONG.

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, EPOCH_YEAR, FALSE, HOURSPERDAY, increment_overflow(), isleap, localsub(), MINSPERHOUR, MONSPERYEAR, normalize_overflow(), SECSPERMIN, t, TM_YEAR_BASE, tmcomp(), TRUE, ttinfo::tt_gmtoff, ttinfo::tt_isdst, state::ttis, TYPE_BIT, TYPE_SIGNED, state::typecnt, and WRONG.

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

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

Referenced by gmtsub(), and localsub().

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

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

Definition at line 1269 of file localtime.c.

References result.

Referenced by time2().

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

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

Referenced by tzparse().

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

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

Definition at line 239 of file localtime.c.

References state::ats, state::charcnt, state::chars, detzcode(), FALSE, FILENAME_MAX, state::leapcnt, lsinfo::ls_corr, lsinfo::ls_trans, state::lsis, OPEN_MODE, state::timecnt, TRUE, ttinfo::tt_abbrind, ttinfo::tt_gmtoff, ttinfo::tt_isdst, ttinfo::tt_ttisgmt, ttinfo::tt_ttisstd, state::ttis, state::typecnt, state::types, 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().

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

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

Definition at line 644 of file localtime.c.

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

Referenced by gmtload(), and P().

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

## Variable Documentation

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

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

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

int gmt_is_set`[static]`

Definition at line 212 of file localtime.c.

struct state* gmtptr = NULL`[static]`

Definition at line 206 of file localtime.c.

struct state* last_lclptr = NULL`[static]`

Definition at line 205 of file localtime.c.

struct state* lclptr = NULL`[static]`

Definition at line 204 of file localtime.c.

const int mon_lengths[2][MONSPERYEAR]`[static]`

Initial value:

     {
       { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
       { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
    }

Definition at line 392 of file localtime.c.

char wildabbr[] = "WILDABBR"`[static]`

Definition at line 110 of file localtime.c.

Referenced by gmtsub().

const int year_lengths[2]`[static]`

Initial value:

     {
       DAYSPERNYEAR, DAYSPERLYEAR
    }

Definition at line 397 of file localtime.c.