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

📄 ctime.c

📁 Algorithms for Image Processing and Computer Vision Source Code
💻 C
📖 第 1 页 / 共 3 页
字号:
		return NULL;
	*secsp = num * SECSPERHOUR;
	if (*strp == ':') {
		++strp;
		strp = getnum(strp, &num, 0, MINSPERHOUR - 1);
		if (strp == NULL)
			return NULL;
		*secsp += num * SECSPERMIN;
		if (*strp == ':') {
			++strp;
			strp = getnum(strp, &num, 0, SECSPERMIN - 1);
			if (strp == NULL)
				return NULL;
			*secsp += num;
		}
	}
	return strp;
}

/*
** Given a pointer into a time zone string, extract an offset, in
** [+-]hh[:mm[:ss]] form, from the string.
** If any error occurs, return NULL.
** Otherwise, return a pointer to the first character not part of the time.
*/

static const char *
getoffset(strp, offsetp)
register const char *	strp;
long * const		offsetp;
{
	register 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(strp, rulep)
const char *			strp;
register struct rule * 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(janfirst, year, rulep, offset)
const time_t				janfirst;
const int				year;
register const struct rule * const	rulep;
const long				offset;
{
  register int	leapyear;
  register time_t	value=0;
  register 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(name, sp, lastditch)
const char *			name;
register struct state * const	sp;
const int			lastditch;
{
  const char *			stdname;
  const char *			dstname=0;
  int				stdlen;
  int				dstlen;
  long				stdoffset;
  long				dstoffset;
  register time_t *		atp;
  register unsigned char *	typep;
  register char *			cp;
  register int			load_result;

  stdname = name;
  if (lastditch) {
    stdlen = strlen(name);	/* length of standard zone name */
    name += stdlen;
    if (stdlen >= sizeof sp->chars)
      stdlen = (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;
      register int	year;
      register 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;
      register 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) {
	register 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 > 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(sp)
struct state * const	sp;
{
	if (tzload(GMT, sp) != 0)
		(void) tzparse(GMT, sp, TRUE);
}

void
tzset()
{
  register const char *	name;
  void tzsetwall();

  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)
      (void) gmtload(lclptr);
  settzname();
}

void
tzsetwall()
{
	lcl_is_set = TRUE;
#ifdef ALL_STATE
	if (lclptr == NULL) {
		lclptr = (struct state *) malloc(sizeof *lclptr);
		if (lclptr == NULL) {
			settzname();	/* all we can do */

⌨️ 快捷键说明

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