Home
       mktime.c - scc - simple c99 compiler
  HTML git clone git://git.simple-cc.org/scc
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
   DIR README
   DIR LICENSE
       ---
       mktime.c (1886B)
       ---
            1 #include <limits.h>
            2 #include <time.h>
            3 
            4 #include "../libc.h"
            5 
            6 #undef mktime
            7 
            8 static int
            9 norm(int *val, int *next, int max)
           10 {
           11         int v = *val, n = *next, d;
           12 
           13         if (v < 0) {
           14                 d = -v / max + 1;
           15                 v += d * max;
           16                 if (n > INT_MAX - d)
           17                         return 0;
           18                 n -= d;
           19         }
           20         if (v >= max) {
           21                 d = v / max;
           22                 v -= d * max;
           23                 if (n < INT_MIN + d)
           24                         return 0;
           25                 n += d;
           26         }
           27 
           28         *val = v;
           29         *next = n;
           30         return 1;
           31 }
           32 
           33 static int
           34 normalize(struct tm *tm)
           35 {
           36         int mon, day, year, yday;
           37 
           38         /*
           39          * Normalize sec so that it doesn't over/underflow min
           40          * Normalize min so that it doesn't over/underflow hour
           41          * Normalize hour so that it doesn't over/underflow mday
           42          * Normalize month so that it doesn't over/underflow year
           43          */
           44         if (!norm(&tm->tm_sec, &tm->tm_min, 60)
           45         || !norm(&tm->tm_min, &tm->tm_hour, 60)
           46         || !norm(&tm->tm_hour, &tm->tm_mday, 24)
           47         || !norm(&tm->tm_mon, &tm->tm_year, 12))
           48                 return 0;
           49 
           50         if (tm->tm_year < 0)
           51                 return 0;
           52 
           53         day = tm->tm_mday;
           54         yday = 0;
           55         year = MINYEAR + tm->tm_year;
           56 
           57         if (year > _MAXYEAR)
           58                 return 0;
           59 
           60         _daysmon[FEB] = FEBDAYS(year);
           61 
           62         /*
           63          * Normalize mday so that it doesn't over/underflow month
           64          * Normalize month so that it doesn't over/underflow year
           65          */
           66         for (mon = tm->tm_mon; day < 1; --mon) {
           67                 if (mon == JAN) {
           68                         if (year == MINYEAR)
           69                                 return 0;
           70                         year--;
           71                         _daysmon[FEB] = FEBDAYS(year);
           72                         mon = DEC+1;
           73                 }
           74                 day += _daysmon[mon-1];
           75         }
           76 
           77         for (; day > _daysmon[mon]; ++mon) {
           78                 day -= _daysmon[mon];
           79                 if (mon == DEC) {
           80                         if (year == _MAXYEAR)
           81                                 return 0;
           82                         year++;
           83                         _daysmon[FEB] = FEBDAYS(year);
           84                         mon = JAN-1;
           85                 }
           86         }
           87 
           88         for (int i = 0; i < mon; ++i)
           89                 yday += _daysmon[i];
           90 
           91         tm->tm_mon = mon;
           92         tm->tm_year = year - MINYEAR;
           93         tm->tm_mday = day;
           94         tm->tm_yday = yday + day - 1;
           95         tm->tm_wday = (_newyear(tm->tm_year) + tm->tm_yday) % 7;
           96         tm->tm_isdst = 0;
           97         return 1;
           98 }
           99 
          100 time_t
          101 mktime(struct tm *tm)
          102 {
          103         if (!normalize(tm))
          104                 return -1;
          105         return _systime(tm);
          106 }