⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ctime.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 3 页
字号:
*/

static const char *
getoffset(const char *strp, long * CPP_CONST offsetp)
{
  int neg;

  if (*strp == '-')
  {
    neg = 1;
    ++strp;
  }
  else if (isdigit(*strp) || *strp++ == '+')
    neg = 0;
  else
    return NULL; /* illegal offset */
  strp = getsecs(strp, offsetp);
  if (strp == NULL)
    return NULL; /* illegal time */
  if (neg)
    *offsetp = -*offsetp;
  return strp;
}

/*
** Given a pointer into a time zone string, extract a rule in the form
** date[/time].  See POSIX section 8 for the format of "date" and "time".
** If a valid rule is not found, return NULL.
** Otherwise, return a pointer to the first character not part of the rule.
*/

static const char *
getrule(const char *strp, struct rule * CPP_CONST rulep)
{
  if (*strp == 'J')
  {
    /*
     ** Julian day.
     */
    rulep->r_type = JULIAN_DAY;
    ++strp;
    strp = getnum(strp, &rulep->r_day, 1, DAYSPERNYEAR);
  }
  else if (*strp == 'M')
  {
    /*
     ** Month, week, day.
     */
    rulep->r_type = MONTH_NTH_DAY_OF_WEEK;
    ++strp;
    strp = getnum(strp, &rulep->r_mon, 1, MONSPERYEAR);
    if (strp == NULL)
      return NULL;
    if (*strp++ != '.')
      return NULL;
    strp = getnum(strp, &rulep->r_week, 1, 5);
    if (strp == NULL)
      return NULL;
    if (*strp++ != '.')
      return NULL;
    strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1);
  }
  else if (isdigit(*strp))
  {
    /*
     ** Day of year.
     */
    rulep->r_type = DAY_OF_YEAR;
    strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1);
  }
  else
    return NULL;        /* invalid format */
  if (strp == NULL)
    return NULL;
  if (*strp == '/')
  {
    /*
     ** Time specified.
     */
    ++strp;
    strp = getsecs(strp, &rulep->r_time);
  }
  else
    rulep->r_time = 2 * SECSPERHOUR; /* default = 2:00:00 */
  return strp;
}

/*
** 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 time_t
transtime(const time_t janfirst, const int year, const struct rule * CPP_CONST rulep, const long offset)
{
  int leapyear;
  time_t value=0;
  int i;
  int d, m1, yy0, yy1, yy2, dow;

  leapyear = isleap(year);
  switch (rulep->r_type)
  {

  case JULIAN_DAY:
    /*
     ** Jn - Julian day, 1 == January 1, 60 == March 1 even in leap
     ** years.
     ** In non-leap years, or if the day number is 59 or less, just
     ** add SECSPERDAY times the day number-1 to the time of
     ** January 1, midnight, to get the day.
     */
    value = janfirst + (rulep->r_day - 1) * SECSPERDAY;
    if (leapyear && rulep->r_day >= 60)
      value += SECSPERDAY;
    break;

  case DAY_OF_YEAR:
    /*
     ** n - day of year.
     ** Just add SECSPERDAY times the day number to the time of
     ** January 1, midnight, to get the day.
     */
    value = janfirst + rulep->r_day * SECSPERDAY;
    break;

  case MONTH_NTH_DAY_OF_WEEK:
    /*
     ** Mm.n.d - nth "dth day" of month m.
     */
    value = janfirst;
    for (i = 0; i < rulep->r_mon - 1; ++i)
      value += mon_lengths[leapyear][i] * SECSPERDAY;

    /*
     ** Use Zeller's Congruence to get day-of-week of first day of
     ** month.
     */
    m1 = (rulep->r_mon + 9) % 12 + 1;
    yy0 = (rulep->r_mon <= 2) ? (year - 1) : year;
    yy1 = yy0 / 100;
    yy2 = yy0 % 100;
    dow = ((26 * m1 - 2) / 10 +
       1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7;
    if (dow < 0)
      dow += DAYSPERWEEK;

    /*
     ** "dow" is the day-of-week of the first day of the month.  Get
     ** the day-of-month (zero-origin) of the first "dow" day of the
     ** month.
     */
    d = rulep->r_day - dow;
    if (d < 0)
      d += DAYSPERWEEK;
    for (i = 1; i < rulep->r_week; ++i)
    {
      if (d + DAYSPERWEEK >=
      mon_lengths[leapyear][rulep->r_mon - 1])
    break;
      d += DAYSPERWEEK;
    }

    /*
     ** "d" is the day-of-month (zero-origin) of the day we want.
     */
    value += d * SECSPERDAY;
    break;
  }

  /*
   ** "value" is the Epoch-relative time of 00:00:00 GMT on the day in
   ** question.  To get the Epoch-relative time of the specified local
   ** time on that day, add the transition time and the current offset
   ** from GMT.
   */
  return value + rulep->r_time + offset;
}

/*
** Given a POSIX section 8-style TZ string, fill in the rule tables as
** appropriate.
*/

static int
tzparse(const char *name, struct state * CPP_CONST sp, const int lastditch)
{
  const char * stdname;
  const char * dstname=0;
  int stdlen;
  int dstlen;
  long stdoffset;
  long dstoffset;
  time_t * atp;
  unsigned char * typep;
  char * cp;
  int load_result;

  stdname = name;
  if (lastditch)
  {
    stdlen = strlen(name);  /* length of standard zone name */
    name += stdlen;
    if (stdlen >= (int)sizeof sp->chars)
      stdlen = (int)(sizeof sp->chars) - 1;
  }
  else
  {
    name = getzname(name);
    stdlen = name - stdname;
    if (stdlen < 3)
      return -1;
  }
  if (*name == '\0')
    return -1;
  else
  {
    name = getoffset(name, &stdoffset);
    if (name == NULL)
      return -1;
  }
  load_result = tzload(TZDEFRULES, sp);
  if (load_result != 0)
    sp->leapcnt = 0;        /* so, we're off a little */
  if (*name != '\0')
  {
    dstname = name;
    name = getzname(name);
    dstlen = name - dstname;    /* length of DST zone name */
    if (dstlen < 3)
      return -1;
    if (*name != '\0' && *name != ',' && *name != ';')
    {
      name = getoffset(name, &dstoffset);
      if (name == NULL)
    return -1;
    }
    else
      dstoffset = stdoffset - SECSPERHOUR;
    if (*name == ',' || *name == ';')
    {
      struct rule start;
      struct rule end;
      int year;
      time_t janfirst;
      time_t starttime;
      time_t endtime;

      ++name;
      if ((name = getrule(name, &start)) == NULL)
    return -1;
      if (*name++ != ',')
    return -1;
      if ((name = getrule(name, &end)) == NULL)
    return -1;
      if (*name != '\0')
    return -1;
      sp->typecnt = 2;      /* standard time and DST */
      /*
       ** Two transitions per year, from EPOCH_YEAR to 2037.
       */
      sp->timecnt = 2 * (2037 - EPOCH_YEAR + 1);
      if (sp->timecnt > TZ_MAX_TIMES)
    return -1;
      sp->ttis[0].tt_gmtoff = -dstoffset;
      sp->ttis[0].tt_isdst = 1;
      sp->ttis[0].tt_abbrind = stdlen + 1;
      sp->ttis[1].tt_gmtoff = -stdoffset;
      sp->ttis[1].tt_isdst = 0;
      sp->ttis[1].tt_abbrind = 0;
      atp = sp->ats;
      typep = sp->types;
      janfirst = 0;
      for (year = EPOCH_YEAR; year <= 2037; ++year)
      {
    starttime = transtime(janfirst, year, &start,
                  stdoffset);
    endtime = transtime(janfirst, year, &end,
                dstoffset);
    if (starttime > endtime)
    {
      *atp++ = endtime;
      *typep++ = 1;     /* DST ends */
      *atp++ = starttime;
      *typep++ = 0;     /* DST begins */
    }
    else
    {
      *atp++ = starttime;
      *typep++ = 0;     /* DST begins */
      *atp++ = endtime;
      *typep++ = 1;     /* DST ends */
    }
    janfirst +=
      year_lengths[isleap(year)] * SECSPERDAY;
      }
    }
    else
    {
      int sawstd;
      int sawdst;
      long stdfix;
      long dstfix;
      long oldfix;
      int isdst;
      int i;

      if (*name != '\0')
    return -1;
      if (load_result != 0)
    return -1;
      /*
       ** Compute the difference between the real and
       ** prototype standard and summer time offsets
       ** from GMT, and put the real standard and summer
       ** time offsets into the rules in place of the
       ** prototype offsets.
       */
      sawstd = FALSE;
      sawdst = FALSE;
      stdfix = 0;
      dstfix = 0;
      for (i = 0; i < sp->typecnt; ++i)
      {
    if (sp->ttis[i].tt_isdst)
    {
      oldfix = dstfix;
      dstfix =
        sp->ttis[i].tt_gmtoff + dstoffset;
      if (sawdst && (oldfix != dstfix))
        return -1;
      sp->ttis[i].tt_gmtoff = -dstoffset;
      sp->ttis[i].tt_abbrind = stdlen + 1;
      sawdst = TRUE;
    }
    else
    {
      oldfix = stdfix;
      stdfix =
        sp->ttis[i].tt_gmtoff + stdoffset;
      if (sawstd && (oldfix != stdfix))
        return -1;
      sp->ttis[i].tt_gmtoff = -stdoffset;
      sp->ttis[i].tt_abbrind = 0;
      sawstd = TRUE;
    }
      }
      /*
       ** Make sure we have both standard and summer time.
       */
      if (!sawdst || !sawstd)
    return -1;
      /*
       ** Now correct the transition times by shifting
       ** them by the difference between the real and
       ** prototype offsets.  Note that this difference
       ** can be different in standard and summer time;
       ** the prototype probably has a 1-hour difference
       ** between standard and summer time, but a different
       ** difference can be specified in TZ.
       */
      isdst = FALSE; /* we start in standard time */
      for (i = 0; i < sp->timecnt; ++i)
      {
    const struct ttinfo * ttisp;

    /*
     ** If summer time is in effect, and the
     ** transition time was not specified as
     ** standard time, add the summer time
     ** offset to the transition time;
     ** otherwise, add the standard time offset
     ** to the transition time.
     */
    ttisp = &sp->ttis[sp->types[i]];
    sp->ats[i] +=
      (isdst && !ttisp->tt_ttisstd) ?
        dstfix : stdfix;
    isdst = ttisp->tt_isdst;
      }
    }
  }
  else
  {
    dstlen = 0;
    sp->typecnt = 1;        /* only standard time */
    sp->timecnt = 0;
    sp->ttis[0].tt_gmtoff = -stdoffset;
    sp->ttis[0].tt_isdst = 0;
    sp->ttis[0].tt_abbrind = 0;
  }
  sp->charcnt = stdlen + 1;
  if (dstlen != 0)
    sp->charcnt += dstlen + 1;
  if (sp->charcnt > (int)sizeof sp->chars)
    return -1;
  cp = sp->chars;
  (void) strncpy(cp, stdname, stdlen);
  cp += stdlen;
  *cp++ = '\0';
  if (dstlen != 0)
  {
    (void) strncpy(cp, dstname, dstlen);
    *(cp + dstlen) = '\0';
  }
  return 0;
}

static void
gmtload(struct state * CPP_CONST sp)
{
  if (tzload(GMT, sp) != 0)
    (void) tzparse(GMT, sp, TRUE);
}

/*
 * @implemented
 */
void
_tzset(void)
{
  const char * name;

  name = getenv("TZ");
  if (name == NULL)
  {
    tzsetwall();
    return;
  }
  lcl_is_set = TRUE;
#ifdef ALL_STATE
  if (lclptr == NULL)
  {
    lclptr = (struct state *) malloc(sizeof *lclptr);
    if (lclptr == NULL)
    {
      settzname();      /* all we can do */
      return;
    }
  }
#endif /* defined ALL_STATE */
  if (*name == '\0')
  {
    /*
     ** User wants it fast rather than right.
     */
    lclptr->leapcnt = 0;    /* so, we're off a little */
    lclptr->timecnt = 0;
    lclptr->ttis[0].tt_gmtoff = 0;
    lclptr->ttis[0].tt_abbrind = 0;
    (void) strcpy(lclptr->chars, GMT);
  }
  else if (tzload(name, lclptr) != 0)
    if (name[0] == ':' || tzparse(name, lclptr, FALSE) != 0)
      gmtload(lclptr);
  settzname();
}

void
tzsetwall(void)
{
  lcl_is_set = TRUE;
#ifdef ALL_STATE
  if (lclptr == NULL)
  {
    lclptr = (struct state *) malloc(sizeof *lclptr);
    if (lclptr == NULL)
    {
      settzname();      /* all we can do */
      return;
    }
  }
#endif /* defined ALL_STATE */
  if (tzload((char *) NULL, lclptr) != 0)
    gmtload(lclptr);
  settzname();
}

/*

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -