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

📄 getdate.y

📁 gnu tar 源码包。 tar 软件是 Unix 系统下的一个打包软件
💻 Y
📖 第 1 页 / 共 3 页
字号:
	      if (value != value1)		return '?';	      /* Accumulate fraction, to ns precision.  */	      p++;	      ns = *p++ - '0';	      for (digits = 2; digits <= LOG10_BILLION; digits++)		{		  ns *= 10;		  if (ISDIGIT (*p))		    ns += *p++ - '0';		}	      /* Skip excess digits, truncating toward -Infinity.  */	      if (sign < 0)		for (; ISDIGIT (*p); p++)		  if (*p != '0')		    {		      ns++;		      break;		    }	      while (ISDIGIT (*p))		p++;	      /* Adjust to the timespec convention, which is that		 tv_nsec is always a positive offset even if tv_sec is		 negative.  */	      if (sign < 0 && ns)		{		  s--;		  if (! (s < 0))		    return '?';		  ns = BILLION - ns;		}	      lvalp->timespec.tv_sec = s;	      lvalp->timespec.tv_nsec = ns;	      pc->input = p;	      return sign ? tSDECIMAL_NUMBER : tUDECIMAL_NUMBER;	    }	  else	    {	      lvalp->textintval.negative = sign < 0;	      if (sign < 0)		{		  lvalp->textintval.value = - value;		  if (0 < lvalp->textintval.value)		    return '?';		}	      else		{		  lvalp->textintval.value = value;		  if (lvalp->textintval.value < 0)		    return '?';		}	      lvalp->textintval.digits = p - pc->input;	      pc->input = p;	      return sign ? tSNUMBER : tUNUMBER;	    }	}      if (isalpha (c))	{	  char buff[20];	  char *p = buff;	  table const *tp;	  do	    {	      if (p < buff + sizeof buff - 1)		*p++ = c;	      c = *++pc->input;	    }	  while (isalpha (c) || c == '.');	  *p = '\0';	  tp = lookup_word (pc, buff);	  if (! tp)	    return '?';	  lvalp->intval = tp->value;	  return tp->type;	}      if (c != '(')	return *pc->input++;      count = 0;      do	{	  c = *pc->input++;	  if (c == '\0')	    return c;	  if (c == '(')	    count++;	  else if (c == ')')	    count--;	}      while (count != 0);    }}/* Do nothing if the parser reports an error.  */static intyyerror (parser_control const *pc ATTRIBUTE_UNUSED,	 char const *s ATTRIBUTE_UNUSED){  return 0;}/* If *TM0 is the old and *TM1 is the new value of a struct tm after   passing it to mktime, return true if it's OK that mktime returned T.   It's not OK if *TM0 has out-of-range members.  */static boolmktime_ok (struct tm const *tm0, struct tm const *tm1, time_t t){  if (t == (time_t) -1)    {      /* Guard against falsely reporting an error when parsing a time	 stamp that happens to equal (time_t) -1, on a host that	 supports such a time stamp.  */      tm1 = localtime (&t);      if (!tm1)	return false;    }  return ! ((tm0->tm_sec ^ tm1->tm_sec)	    | (tm0->tm_min ^ tm1->tm_min)	    | (tm0->tm_hour ^ tm1->tm_hour)	    | (tm0->tm_mday ^ tm1->tm_mday)	    | (tm0->tm_mon ^ tm1->tm_mon)	    | (tm0->tm_year ^ tm1->tm_year));}/* A reasonable upper bound for the size of ordinary TZ strings.   Use heap allocation if TZ's length exceeds this.  */enum { TZBUFSIZE = 100 };/* Return a copy of TZ, stored in TZBUF if it fits, and heap-allocated   otherwise.  */static char *get_tz (char tzbuf[TZBUFSIZE]){  char *tz = getenv ("TZ");  if (tz)    {      size_t tzsize = strlen (tz) + 1;      tz = (tzsize <= TZBUFSIZE	    ? memcpy (tzbuf, tz, tzsize)	    : xmemdup (tz, tzsize));    }  return tz;}/* Parse a date/time string, storing the resulting time value into *RESULT.   The string itself is pointed to by P.  Return true if successful.   P can be an incomplete or relative time specification; if so, use   *NOW as the basis for the returned time.  */boolget_date (struct timespec *result, char const *p, struct timespec const *now){  time_t Start;  long int Start_ns;  struct tm const *tmp;  struct tm tm;  struct tm tm0;  parser_control pc;  struct timespec gettime_buffer;  unsigned char c;  bool tz_was_altered = false;  char *tz0 = NULL;  char tz0buf[TZBUFSIZE];  bool ok = true;  if (! now)    {      gettime (&gettime_buffer);      now = &gettime_buffer;    }  Start = now->tv_sec;  Start_ns = now->tv_nsec;  tmp = localtime (&now->tv_sec);  if (! tmp)    return false;  while (c = *p, isspace (c))    p++;  if (strncmp (p, "TZ=\"", 4) == 0)    {      char const *tzbase = p + 4;      size_t tzsize = 1;      char const *s;      for (s = tzbase; *s; s++, tzsize++)	if (*s == '\\')	  {	    s++;	    if (! (*s == '\\' || *s == '"'))	      break;	  }	else if (*s == '"')	  {	    char *z;	    char *tz1;	    char tz1buf[TZBUFSIZE];	    bool large_tz = TZBUFSIZE < tzsize;	    bool setenv_ok;	    tz0 = get_tz (tz0buf);	    z = tz1 = large_tz ? xmalloc (tzsize) : tz1buf;	    for (s = tzbase; *s != '"'; s++)	      *z++ = *(s += *s == '\\');	    *z = '\0';	    setenv_ok = setenv ("TZ", tz1, 1) == 0;	    if (large_tz)	      free (tz1);	    if (!setenv_ok)	      goto fail;	    tz_was_altered = true;	    p = s + 1;	  }    }  /* As documented, be careful to treat the empty string just like     a date string of "0".  Without this, an empty string would be     declared invalid when parsed during a DST transition.  */  if (*p == '\0')    p = "0";  pc.input = p;  pc.year.value = tmp->tm_year;  pc.year.value += TM_YEAR_BASE;  pc.year.digits = 0;  pc.month = tmp->tm_mon + 1;  pc.day = tmp->tm_mday;  pc.hour = tmp->tm_hour;  pc.minutes = tmp->tm_min;  pc.seconds.tv_sec = tmp->tm_sec;  pc.seconds.tv_nsec = Start_ns;  tm.tm_isdst = tmp->tm_isdst;  pc.meridian = MER24;  pc.rel = RELATIVE_TIME_0;  pc.timespec_seen = false;  pc.rels_seen = false;  pc.dates_seen = 0;  pc.days_seen = 0;  pc.times_seen = 0;  pc.local_zones_seen = 0;  pc.dsts_seen = 0;  pc.zones_seen = 0;#if HAVE_STRUCT_TM_TM_ZONE  pc.local_time_zone_table[0].name = tmp->tm_zone;  pc.local_time_zone_table[0].type = tLOCAL_ZONE;  pc.local_time_zone_table[0].value = tmp->tm_isdst;  pc.local_time_zone_table[1].name = NULL;  /* Probe the names used in the next three calendar quarters, looking     for a tm_isdst different from the one we already have.  */  {    int quarter;    for (quarter = 1; quarter <= 3; quarter++)      {	time_t probe = Start + quarter * (90 * 24 * 60 * 60);	struct tm const *probe_tm = localtime (&probe);	if (probe_tm && probe_tm->tm_zone	    && probe_tm->tm_isdst != pc.local_time_zone_table[0].value)	  {	      {		pc.local_time_zone_table[1].name = probe_tm->tm_zone;		pc.local_time_zone_table[1].type = tLOCAL_ZONE;		pc.local_time_zone_table[1].value = probe_tm->tm_isdst;		pc.local_time_zone_table[2].name = NULL;	      }	    break;	  }      }  }#else#if HAVE_TZNAME  {# if !HAVE_DECL_TZNAME    extern char *tzname[];# endif    int i;    for (i = 0; i < 2; i++)      {	pc.local_time_zone_table[i].name = tzname[i];	pc.local_time_zone_table[i].type = tLOCAL_ZONE;	pc.local_time_zone_table[i].value = i;      }    pc.local_time_zone_table[i].name = NULL;  }#else  pc.local_time_zone_table[0].name = NULL;#endif#endif  if (pc.local_time_zone_table[0].name && pc.local_time_zone_table[1].name      && ! strcmp (pc.local_time_zone_table[0].name,		   pc.local_time_zone_table[1].name))    {      /* This locale uses the same abbrevation for standard and	 daylight times.  So if we see that abbreviation, we don't	 know whether it's daylight time.  */      pc.local_time_zone_table[0].value = -1;      pc.local_time_zone_table[1].name = NULL;    }  if (yyparse (&pc) != 0)    goto fail;  if (pc.timespec_seen)    *result = pc.seconds;  else    {      if (1 < (pc.times_seen | pc.dates_seen | pc.days_seen | pc.dsts_seen	       | (pc.local_zones_seen + pc.zones_seen)))	goto fail;      tm.tm_year = to_year (pc.year) - TM_YEAR_BASE;      tm.tm_mon = pc.month - 1;      tm.tm_mday = pc.day;      if (pc.times_seen || (pc.rels_seen && ! pc.dates_seen && ! pc.days_seen))	{	  tm.tm_hour = to_hour (pc.hour, pc.meridian);	  if (tm.tm_hour < 0)	    goto fail;	  tm.tm_min = pc.minutes;	  tm.tm_sec = pc.seconds.tv_sec;	}      else	{	  tm.tm_hour = tm.tm_min = tm.tm_sec = 0;	  pc.seconds.tv_nsec = 0;	}      /* Let mktime deduce tm_isdst if we have an absolute time stamp.  */      if (pc.dates_seen | pc.days_seen | pc.times_seen)	tm.tm_isdst = -1;      /* But if the input explicitly specifies local time with or without	 DST, give mktime that information.  */      if (pc.local_zones_seen)	tm.tm_isdst = pc.local_isdst;      tm0 = tm;      Start = mktime (&tm);      if (! mktime_ok (&tm0, &tm, Start))	{	  if (! pc.zones_seen)	    goto fail;	  else	    {	      /* Guard against falsely reporting errors near the time_t		 boundaries when parsing times in other time zones.  For		 example, suppose the input string "1969-12-31 23:00:00 -0100",		 the current time zone is 8 hours ahead of UTC, and the min		 time_t value is 1970-01-01 00:00:00 UTC.  Then the min		 localtime value is 1970-01-01 08:00:00, and mktime will		 therefore fail on 1969-12-31 23:00:00.  To work around the		 problem, set the time zone to 1 hour behind UTC temporarily		 by setting TZ="XXX1:00" and try mktime again.  */	      long int time_zone = pc.time_zone;	      long int abs_time_zone = time_zone < 0 ? - time_zone : time_zone;	      long int abs_time_zone_hour = abs_time_zone / 60;	      int abs_time_zone_min = abs_time_zone % 60;	      char tz1buf[sizeof "XXX+0:00"			  + sizeof pc.time_zone * CHAR_BIT / 3];	      if (!tz_was_altered)		tz0 = get_tz (tz0buf);	      sprintf (tz1buf, "XXX%s%ld:%02d", "-" + (time_zone < 0),		       abs_time_zone_hour, abs_time_zone_min);	      if (setenv ("TZ", tz1buf, 1) != 0)		goto fail;	      tz_was_altered = true;	      tm = tm0;	      Start = mktime (&tm);	      if (! mktime_ok (&tm0, &tm, Start))		goto fail;	    }	}      if (pc.days_seen && ! pc.dates_seen)	{	  tm.tm_mday += ((pc.day_number - tm.tm_wday + 7) % 7			 + 7 * (pc.day_ordinal - (0 < pc.day_ordinal)));	  tm.tm_isdst = -1;	  Start = mktime (&tm);	  if (Start == (time_t) -1)	    goto fail;	}      if (pc.zones_seen)	{	  long int delta = pc.time_zone * 60;	  time_t t1;#ifdef HAVE_TM_GMTOFF	  delta -= tm.tm_gmtoff;#else	  time_t t = Start;	  struct tm const *gmt = gmtime (&t);	  if (! gmt)	    goto fail;	  delta -= tm_diff (&tm, gmt);#endif	  t1 = Start - delta;	  if ((Start < t1) != (delta < 0))	    goto fail;	/* time_t overflow */	  Start = t1;	}      /* Add relative date.  */      if (pc.rel.year | pc.rel.month | pc.rel.day)	{	  int year = tm.tm_year + pc.rel.year;	  int month = tm.tm_mon + pc.rel.month;	  int day = tm.tm_mday + pc.rel.day;	  if (((year < tm.tm_year) ^ (pc.rel.year < 0))	      | ((month < tm.tm_mon) ^ (pc.rel.month < 0))	      | ((day < tm.tm_mday) ^ (pc.rel.day < 0)))	    goto fail;	  tm.tm_year = year;	  tm.tm_mon = month;	  tm.tm_mday = day;	  tm.tm_hour = tm0.tm_hour;	  tm.tm_min = tm0.tm_min;	  tm.tm_sec = tm0.tm_sec;	  tm.tm_isdst = tm0.tm_isdst;	  Start = mktime (&tm);	  if (Start == (time_t) -1)	    goto fail;	}      /* Add relative hours, minutes, and seconds.  On hosts that support	 leap seconds, ignore the possibility of leap seconds; e.g.,	 "+ 10 minutes" adds 600 seconds, even if one of them is a	 leap second.  Typically this is not what the user wants, but it's	 too hard to do it the other way, because the time zone indicator	 must be applied before relative times, and if mktime is applied	 again the time zone will be lost.  */      {	long int sum_ns = pc.seconds.tv_nsec + pc.rel.ns;	long int normalized_ns = (sum_ns % BILLION + BILLION) % BILLION;	time_t t0 = Start;	long int d1 = 60 * 60 * pc.rel.hour;	time_t t1 = t0 + d1;	long int d2 = 60 * pc.rel.minutes;	time_t t2 = t1 + d2;	long int d3 = pc.rel.seconds;	time_t t3 = t2 + d3;	long int d4 = (sum_ns - normalized_ns) / BILLION;	time_t t4 = t3 + d4;	if ((d1 / (60 * 60) ^ pc.rel.hour)	    | (d2 / 60 ^ pc.rel.minutes)	    | ((t1 < t0) ^ (d1 < 0))	    | ((t2 < t1) ^ (d2 < 0))	    | ((t3 < t2) ^ (d3 < 0))	    | ((t4 < t3) ^ (d4 < 0)))	  goto fail;	result->tv_sec = t4;	result->tv_nsec = normalized_ns;      }    }  goto done; fail:  ok = false; done:  if (tz_was_altered)    ok &= (tz0 ? setenv ("TZ", tz0, 1) : unsetenv ("TZ")) == 0;  if (tz0 != tz0buf)    free (tz0);  return ok;}#if TESTintmain (int ac, char **av){  char buff[BUFSIZ];  printf ("Enter date, or blank line to exit.\n\t> ");  fflush (stdout);  buff[BUFSIZ - 1] = '\0';  while (fgets (buff, BUFSIZ - 1, stdin) && buff[0])    {      struct timespec d;      struct tm const *tm;      if (! get_date (&d, buff, NULL))	printf ("Bad format - couldn't convert.\n");      else if (! (tm = localtime (&d.tv_sec)))	{	  long int sec = d.tv_sec;	  printf ("localtime (%ld) failed\n", sec);	}      else	{	  int ns = d.tv_nsec;	  printf ("%04ld-%02d-%02d %02d:%02d:%02d.%09d\n",		  tm->tm_year + 1900L, tm->tm_mon + 1, tm->tm_mday,		  tm->tm_hour, tm->tm_min, tm->tm_sec, ns);	}      printf ("\t> ");      fflush (stdout);    }  return 0;}#endif /* TEST */

⌨️ 快捷键说明

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