partime.c

来自「这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易」· C语言 代码 · 共 743 行 · 第 1/2 页

C
743
字号
/* Parse an initial prefix of S; it must denote a time zone.   Set *ZONE to the number of seconds east of GMT,   or to TM_LOCAL_ZONE if it is the local time zone.   Return the first character after the prefix, or 0 if it wasn't parsed.  */char *parzone (s, zone)     char const *s;     long *zone;{  char sign;  int hh, mm, ss;  int minutesEastOfUTC;  long offset, z;  /* The formats are LT, n, n DST, nDST, no, o     where n is a time zone name     and o is a time zone offset of the form [-+]hh[:mm[:ss]].  */  switch (*s)    {    case '-':    case '+':      z = 0;      break;    default:      minutesEastOfUTC = lookup (s, zone_names);      if (minutesEastOfUTC == -1)	return 0;      /* Don't bother to check rest of spelling.  */      while (ISALPHA ((unsigned char) *s))	s++;      /* Don't modify LT.  */      if (minutesEastOfUTC == 1)	{	  *zone = TM_LOCAL_ZONE;	  return (char *) s;	}      z = minutesEastOfUTC * 60L;      /* Look for trailing " DST".  */      if ((s[-1] == 'T' || s[-1] == 't')	  && (s[-2] == 'S' || s[-2] == 's')	  && (s[-3] == 'D' || s[-3] == 'd'))	goto trailing_dst;      while (ISSPACE ((unsigned char) *s))	s++;      if ((s[0] == 'D' || s[0] == 'd')	  && (s[1] == 'S' || s[1] == 's')	  && (s[2] == 'T' || s[2] == 't'))	{	  s += 3;	trailing_dst:	  *zone = z + 60*60;	  return (char *) s;	}      switch (*s)	{	case '-':	case '+':	  break;	default:	  *zone = z;	  return (char *) s;	}      break;    }  sign = *s++;  if (! (s = parse_ranged (s, 2, 0, 23, &hh)))    return 0;  mm = ss = 0;  if (*s == ':')    s++;  if (ISDIGIT (*s))    {      if (! (s = parse_ranged (s, 2, 0, 59, &mm)))	return 0;      if (*s == ':' && s[-3] == ':' && ISDIGIT (s[1])	  && ! (s = parse_ranged (s + 1, 2, 0, 59, &ss)))	return 0;    }  if (ISDIGIT (*s))    return 0;  offset = (hh * 60 + mm) * 60L + ss;  *zone = z + (sign == '-' ? -offset : offset);  /* ?? Are fractions allowed here?  If so, they're not implemented.  */  return (char *) s;}/* Parse an initial prefix of S, matching the pattern whose code is C.   Set *T accordingly.   Return the first character after the prefix, or 0 if it wasn't parsed.  */static char const *parse_pattern_letter (s, c, t)     char const *s;     int c;     struct partime *t;{  switch (c)    {    case '$': /* The next character must be a non-digit.  */      if (ISDIGIT (*s))	return 0;      break;    case '-':    case '/':    case ':':      /* These characters stand for themselves.  */      if (*s++ != c)	return 0;      break;    case '4': /* 4-digit year */      s = parse_fixed (s, 4, &t->tm.tm_year);      break;    case '=': /* optional '-' */      s += *s == '-';      break;    case 'A': /* AM or PM */      /* This matches the regular expression [AaPp][Mm]?.         It must not be followed by a letter or digit;         otherwise it would match prefixes of strings like "PST".  */      switch (*s++)	{	case 'A':	case 'a':	  if (t->tm.tm_hour == 12)	    t->tm.tm_hour = 0;	  break;	case 'P':	case 'p':	  if (t->tm.tm_hour != 12)	    t->tm.tm_hour += 12;	  break;	default:	  return 0;	}      switch (*s)	{	case 'M':	case 'm':	  s++;	  break;	}      if (ISALNUM ((unsigned char) *s))	return 0;      break;    case 'D': /* day of month [01-31] */      s = parse_ranged (s, 2, 1, 31, &t->tm.tm_mday);      break;    case 'd': /* day of year [001-366] */      s = parse_ranged (s, 3, 1, 366, &t->tm.tm_yday);      t->tm.tm_yday--;      break;    case 'E': /* extended day of month [1-9, 01-31] */      s = parse_ranged (s, (ISDIGIT (s[0]) && ISDIGIT (s[1])) + 1, 1, 31,			&t->tm.tm_mday);      break;    case 'h': /* hour [00-23 followed by optional fraction] */      {	int frac;	s = parse_decimal (s, 2, 0, 23, 60 * 60, &t->tm.tm_hour, &frac);	t->tm.tm_min = frac / 60;	t->tm.tm_sec = frac % 60;      }      break;    case 'm': /* minute [00-59 followed by optional fraction] */      s = parse_decimal (s, 2, 0, 59, 60, &t->tm.tm_min, &t->tm.tm_sec);      break;    case 'n': /* month name [e.g. "Jan"] */      if (! TM_DEFINED (t->tm.tm_mon = lookup (s, month_names)))	return 0;      /* Don't bother to check rest of spelling.  */      while (ISALPHA ((unsigned char) *s))	s++;      break;    case 'N': /* month [01-12] */      s = parse_ranged (s, 2, 1, 12, &t->tm.tm_mon);      t->tm.tm_mon--;      break;    case 'r': /* year % 10 (remainder in origin-0 decade) [0-9] */      s = parse_fixed (s, 1, &t->tm.tm_year);      t->ymodulus = 10;      break;    case_R:    case 'R': /* year % 100 (remainder in origin-0 century) [00-99] */      s = parse_fixed (s, 2, &t->tm.tm_year);      t->ymodulus = 100;      break;    case 's': /* second [00-60 followed by optional fraction] */      {	int frac;	s = parse_decimal (s, 2, 0, 60, 1, &t->tm.tm_sec, &frac);	t->tm.tm_sec += frac;      }      break;    case 'T': /* 'T' or 't' */      switch (*s++)	{	case 'T':	case 't':	  break;	default:	  return 0;	}      break;    case 't': /* traditional hour [1-9 or 01-12] */      s = parse_ranged (s, (ISDIGIT (s[0]) && ISDIGIT (s[1])) + 1, 1, 12,			&t->tm.tm_hour);      break;    case 'w': /* 'W' or 'w' only (stands for current week) */      switch (*s++)	{	case 'W':	case 'w':	  break;	default:	  return 0;	}      break;    case 'W': /* 'W' or 'w', followed by a week of year [00-53] */      switch (*s++)	{	case 'W':	case 'w':	  break;	default:	  return 0;	}      s = parse_ranged (s, 2, 0, 53, &t->yweek);      break;    case 'X': /* weekday (1=Mon ... 7=Sun) [1-7] */      s = parse_ranged (s, 1, 1, 7, &t->tm.tm_wday);      t->tm.tm_wday--;      break;    case 'x': /* weekday name [e.g. "Sun"] */      if (! TM_DEFINED (t->tm.tm_wday = lookup (s, weekday_names)))	return 0;      /* Don't bother to check rest of spelling.  */      while (ISALPHA ((unsigned char) *s))	s++;      break;    case 'y': /* either R or Y */      if (ISDIGIT (s[0]) && ISDIGIT (s[1]) && ! ISDIGIT (s[2]))	goto case_R;      /* fall into */    case 'Y': /* year in full [4 or more digits] */      {	int len = 0;	while (ISDIGIT (s[len]))	  len++;	if (len < 4)	  return 0;	s = parse_fixed (s, len, &t->tm.tm_year);      }      break;    case 'Z': /* time zone */      s = parzone (s, &t->zone);      break;    case '_': /* possibly empty sequence of non-alphanumerics */      while (! ISALNUM ((unsigned char) *s) && *s)	s++;      break;    default: /* bad pattern */      return 0;    }  return s;}/* If there is no conflict, merge into *T the additional information in *U   and return 0.  Otherwise do nothing and return -1.  */static intmerge_partime (t, u)     struct partime *t;     struct partime const *u;{# define conflict(a,b) ((a) != (b)  &&  TM_DEFINED (a)  &&  TM_DEFINED (b))  if (conflict (t->tm.tm_sec, u->tm.tm_sec)      || conflict (t->tm.tm_min, u->tm.tm_min)      || conflict (t->tm.tm_hour, u->tm.tm_hour)      || conflict (t->tm.tm_mday, u->tm.tm_mday)      || conflict (t->tm.tm_mon, u->tm.tm_mon)      || conflict (t->tm.tm_year, u->tm.tm_year)      || conflict (t->tm.tm_wday, u->tm.tm_yday)      || conflict (t->ymodulus, u->ymodulus)      || conflict (t->yweek, u->yweek)      || (t->zone != u->zone	  && t->zone != TM_UNDEFINED_ZONE	  && u->zone != TM_UNDEFINED_ZONE))    return -1;# undef conflict# define merge_(a,b) if (TM_DEFINED (b)) (a) = (b);  merge_ (t->tm.tm_sec, u->tm.tm_sec)  merge_ (t->tm.tm_min, u->tm.tm_min)  merge_ (t->tm.tm_hour, u->tm.tm_hour)  merge_ (t->tm.tm_mday, u->tm.tm_mday)  merge_ (t->tm.tm_mon, u->tm.tm_mon)  merge_ (t->tm.tm_year, u->tm.tm_year)  merge_ (t->tm.tm_wday, u->tm.tm_yday)  merge_ (t->ymodulus, u->ymodulus)  merge_ (t->yweek, u->yweek)# undef merge_  if (u->zone != TM_UNDEFINED_ZONE)    t->zone = u->zone;  return 0;}/* Parse a date/time prefix of S, putting the parsed result into *T.   Return the first character after the prefix.   The prefix may contain no useful information;   in that case, *T will contain only undefined values.  */char *partime (s, t)     char const *s;     struct partime *t;{  struct partime p;  undefine (t);  while (*s)    {      int i = 0;      char const *s1;      do	{	  if (! (s1 = parse_prefix (s, &p, &i)))	    return (char *) s;	}      while (merge_partime (t, &p) != 0);      s = s1;    }  return (char *) s;}

⌨️ 快捷键说明

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