text: /* _PDCLIB_timesub( const time_t *, int_fast32_t, const struct state *, struct tm * )
  
     This file is part of the Public Domain C Library (PDCLib).
     Permission is granted to use, modify, and / or redistribute at will.
  */
  
  #ifndef REGTEST
  
  #include "pdclib/_PDCLIB_tzcode.h"
  
  /* Return the number of leap years through the end of the given year
     where, to make the math easy, the answer for year zero is defined as zero.
  */
  static int leaps_thru_end_of_nonneg( int y )
  {
      return y / 4 - y / 100 + y / 400;
  }
  
  static int leaps_thru_end_of( const int y )
  {
      return ( y < 0
          ? -1 - leaps_thru_end_of_nonneg( -1 - y )
          : leaps_thru_end_of_nonneg( y ) );
  }
  
  struct tm * _PDCLIB_timesub( const time_t * timep, int_fast32_t offset, const struct state * sp, struct tm * tmp )
  {
      const struct lsinfo * lp;
      time_t                tdays;
      int                   idays;  /* unsigned would be so 2003 */
      int_fast64_t          rem;
      int                   y;
      const int *           ip;
      int_fast64_t          corr;
      bool                  hit;
      int                   i;
  
      corr = 0;
      hit = false;
      i = ( sp == NULL ) ? 0 : sp->leapcnt;
  
      while ( --i >= 0 )
      {
          lp = &sp->lsis[ i ];
          if ( *timep >= lp->trans )
          {
              corr = lp->corr;
              hit = ( *timep == lp->trans && ( i == 0 ? 0 : lp[ -1 ].corr ) < corr );
              break;
          }
      }
  
      y = EPOCH_YEAR;
      tdays = *timep / SECSPERDAY;
      rem = *timep % SECSPERDAY;
  
      while ( tdays < 0 || tdays >= year_lengths[ _PDCLIB_is_leap( y ) ] )
      {
          int    newy;
          time_t tdelta;
          int    idelta;
          int    leapdays;
  
          tdelta = tdays / DAYSPERLYEAR;
  
          if ( ! ( ( ! _PDCLIB_TYPE_SIGNED( time_t ) || _PDCLIB_INT_MIN <= tdelta ) && tdelta <= _PDCLIB_INT_MAX ) )
          {
              goto out_of_range;
          }
  
          idelta = tdelta;
  
          if ( idelta == 0 )
          {
              idelta = ( tdays < 0 ) ? -1 : 1;
          }
  
          newy = y;
  
          if ( _PDCLIB_increment_overflow( &newy, idelta ) )
          {
              goto out_of_range;
          }
  
          leapdays = leaps_thru_end_of( newy - 1 ) - leaps_thru_end_of( y - 1 );
          tdays -= ( (time_t)newy - y ) * DAYSPERNYEAR;
          tdays -= leapdays;
          y = newy;
      }
  
      /* Given the range, we can now fearlessly cast... */
      idays = tdays;
      rem += offset - corr;
  
      while ( rem < 0 )
      {
          rem += SECSPERDAY;
          --idays;
      }
  
      while ( rem >= SECSPERDAY )
      {
          rem -= SECSPERDAY;
          ++idays;
      }
  
      while ( idays < 0 )
      {
          if ( _PDCLIB_increment_overflow( &y, -1 ) )
          {
              goto out_of_range;
          }
  
          idays += year_lengths[ _PDCLIB_is_leap( y ) ];
      }
  
      while ( idays >= year_lengths[ _PDCLIB_is_leap( y ) ] )
      {
          idays -= year_lengths[ _PDCLIB_is_leap( y ) ];
  
          if ( _PDCLIB_increment_overflow( &y, 1 ) )
          {
              goto out_of_range;
          }
      }
  
      tmp->tm_year = y;
  
      if ( _PDCLIB_increment_overflow( &tmp->tm_year, -TM_YEAR_BASE ) )
      {
          goto out_of_range;
      }
  
      tmp->tm_yday = idays;
      /* The "extra" mods below avoid overflow problems. */
      tmp->tm_wday = EPOCH_WDAY +
          ( ( y - EPOCH_YEAR ) % DAYSPERWEEK ) *
          ( DAYSPERNYEAR % DAYSPERWEEK ) +
          leaps_thru_end_of( y - 1 ) -
          leaps_thru_end_of( EPOCH_YEAR - 1 ) +
          idays;
      tmp->tm_wday %= DAYSPERWEEK;
  
      if ( tmp->tm_wday < 0 )
      {
          tmp->tm_wday += DAYSPERWEEK;
      }
  
      tmp->tm_hour = (int)( rem / SECSPERHOUR );
      rem %= SECSPERHOUR;
      tmp->tm_min = (int)( rem / SECSPERMIN );
  
      /* A positive leap second requires a special
         representation. This uses "... ??:59:60" et seq.
      */
      tmp->tm_sec = (int) ( rem % SECSPERMIN ) + hit;
      ip = mon_lengths[ _PDCLIB_is_leap( y ) ];
  
      for ( tmp->tm_mon = 0; idays >= ip[ tmp->tm_mon ]; ++( tmp->tm_mon ) )
      {
          idays -= ip[ tmp->tm_mon ];
      }
  
      tmp->tm_mday = (int)( idays + 1 );
      tmp->tm_isdst = 0;
  #ifdef TM_GMTOFF
      tmp->TM_GMTOFF = offset;
  #endif /* defined TM_GMTOFF */
      return tmp;
  
   out_of_range:
      *_PDCLIB_errno_func() = _PDCLIB_EOVERFLOW;
      return NULL;
  }
  
  #endif
  
  #ifdef TEST
  
  #include "_PDCLIB_test.h"
  
  int main( void )
  {
  #ifndef REGTEST
  #endif
  
      return TEST_RESULTS;
  }
  
  #endif
  