rem: 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) return Start; }  if (pc.zones_seen) { int delta = pc.time_zone * 60; #ifdef HAVE_TM_GMTOFF delta -= tm.tm_gmtoff; #else struct tm *gmt = gmtime (&Start); if (! gmt) return -1; delta -= tm_diff (&tm, gmt); #endif if ((Start < Start - delta) != (delta < 0)) return -1;	 Start -= delta; }   { time_t t0 = Start; long d1 = 60 * 60 * (long) pc.rel_hour; time_t t1 = t0 + d1; long d2 = 60 * (long) pc.rel_minutes; time_t t2 = t1 + d2; int d3 = pc.rel_seconds; time_t t3 = t2 + d3; if ((d1 / (60 * 60) ^ pc.rel_hour) | (d2 / 60 ^ pc.rel_minutes) | ((t0 + d1 < t0) ^ (d1 < 0)) | ((t1 + d2 < t1) ^ (d2 < 0)) | ((t2 + d3 < t2) ^ (d3 < 0))) return -1; Start = t3; }  return Start;
add: 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;
context: get_date (const char *p, const time_t *now){  time_t Start = now ? *now : time (0);  struct tm *tmp = localtime (&Start);  struct tm tm;  struct tm tm0;  parser_control pc;  if (! tmp)    return -1;  pc.input = p;  pc.year.value = tmp->tm_year + TM_YEAR_BASE;  pc.year.digits = 4;  pc.month = tmp->tm_mon + 1;  pc.day = tmp->tm_mday;  pc.hour = tmp->tm_hour;  pc.minutes = tmp->tm_min;  pc.seconds = tmp->tm_sec;  tm.tm_isdst = tmp->tm_isdst;  pc.meridian = MER24;  pc.rel_seconds = 0;  pc.rel_minutes = 0;  pc.rel_hour = 0;  pc.rel_day = 0;  pc.rel_month = 0;  pc.rel_year = 0;  pc.dates_seen = 0;  pc.days_seen = 0;  pc.rels_seen = 0;  pc.times_seen = 0;  pc.local_zones_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 = 0;  /* 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 *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 = 0;	      }	    break;	  }      }  }#else#if HAVE_TZNAME  {# ifndef 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 = 0;  }#else  pc.local_time_zone_table[0].name = 0;#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 = 0;    }  if (yyparse (&pc) != 0      || 1 < pc.times_seen || 1 < pc.dates_seen || 1 < pc.days_seen      || 1 < (pc.local_zones_seen + pc.zones_seen)      || (pc.local_zones_seen && 1 < pc.local_isdst))    return -1;  tm.tm_year = to_year (pc.year) - TM_YEAR_BASE + pc.rel_year;  tm.tm_mon = pc.month - 1 + pc.rel_month;  tm.tm_mday = pc.day + pc.rel_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)	return -1;      tm.tm_min = pc.minutes;      tm.tm_sec = pc.seconds;    }  else    {      tm.tm_hour = tm.tm_min = tm.tm_sec = 0;    }  /* Let mktime deduce tm_isdst if we have an absolute time stamp,     or if the relative time stamp mentions days, months, or years.  */  if (pc.dates_seen | pc.days_seen | pc.times_seen | pc.rel_day      | pc.rel_month | pc.rel_year)    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 (Start == (time_t) -1)    {      /* Guard against falsely reporting errors near the time_t boundaries         when parsing times in other time zones.  For example, if the min         time_t value is 1970-01-01 00:00:00 UTC and we are 8 hours ahead         of UTC, then the min localtime value is 1970-01-01 08:00:00; if         we apply mktime to 1970-01-01 00:00:00 we will get an error, so         we apply mktime to 1970-01-02 08:00:00 instead and adjust the time         zone by 24 hours to compensate.  This algorithm assumes that         there is no DST transition within a day of the time_t boundaries.  */      if (pc.zones_seen)	{	  tm = tm0;	  if (tm.tm_year <= EPOCH_YEAR - TM_YEAR_BASE)	    {	      tm.tm_mday++;	      pc.time_zone += 24 * 60;	    }	  else	    {	      tm.tm_mday--;	      pc.time_zone -= 24 * 60;	    }	  Start = mktime (&tm);	}      if (Start == (time_t) -1)	return Start;    }  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)	return Start;    }  if (pc.zones_seen)    {      int delta = pc.time_zone * 60;#ifdef HAVE_TM_GMTOFF      delta -= tm.tm_gmtoff;#else      struct tm *gmt = gmtime (&Start);      if (! gmt)	return -1;      delta -= tm_diff (&tm, gmt);#endif      if ((Start < Start - delta) != (delta < 0))	return -1;	/* time_t overflow */      Start -= delta;    }  /* Add relative hours, minutes, and seconds.  Ignore leap seconds;     i.e. "+ 10 minutes" means 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.  */  {    time_t t0 = Start;    long d1 = 60 * 60 * (long) pc.rel_hour;    time_t t1 = t0 + d1;    long d2 = 60 * (long) pc.rel_minutes;    time_t t2 = t1 + d2;    int d3 = pc.rel_seconds;    time_t t3 = t2 + d3;    if ((d1 / (60 * 60) ^ pc.rel_hour)	| (d2 / 60 ^ pc.rel_minutes)	| ((t0 + d1 < t0) ^ (d1 < 0))	| ((t1 + d2 < t1) ^ (d2 < 0))	| ((t2 + d3 < t2) ^ (d3 < 0)))      return -1;    Start = t3;  }  return Start;}