| OLD | NEW | 
|---|
| (Empty) |  | 
|  | 1 #include <stdio.h> | 
|  | 2 #include <stdlib.h> | 
|  | 3 #include <string.h> | 
|  | 4 #include <langinfo.h> | 
|  | 5 #include <locale.h> | 
|  | 6 #include <time.h> | 
|  | 7 #include <limits.h> | 
|  | 8 #include "locale_impl.h" | 
|  | 9 #include "libc.h" | 
|  | 10 #include "time_impl.h" | 
|  | 11 | 
|  | 12 const char *__nl_langinfo_l(nl_item, locale_t); | 
|  | 13 | 
|  | 14 static int is_leap(int y) | 
|  | 15 { | 
|  | 16         /* Avoid overflow */ | 
|  | 17         if (y>INT_MAX-1900) y -= 2000; | 
|  | 18         y += 1900; | 
|  | 19         return !(y%4) && ((y%100) || !(y%400)); | 
|  | 20 } | 
|  | 21 | 
|  | 22 static int week_num(const struct tm *tm) | 
|  | 23 { | 
|  | 24         int val = (tm->tm_yday + 7U - (tm->tm_wday+6U)%7) / 7; | 
|  | 25         /* If 1 Jan is just 1-3 days past Monday, | 
|  | 26          * the previous week is also in this year. */ | 
|  | 27         if ((tm->tm_wday + 371U - tm->tm_yday - 2) % 7 <= 2) | 
|  | 28                 val++; | 
|  | 29         if (!val) { | 
|  | 30                 val = 52; | 
|  | 31                 /* If 31 December of prev year a Thursday, | 
|  | 32                  * or Friday of a leap year, then the | 
|  | 33                  * prev year has 53 weeks. */ | 
|  | 34                 int dec31 = (tm->tm_wday + 7U - tm->tm_yday - 1) % 7; | 
|  | 35                 if (dec31 == 4 || (dec31 == 5 && is_leap(tm->tm_year%400-1))) | 
|  | 36                         val++; | 
|  | 37         } else if (val == 53) { | 
|  | 38                 /* If 1 January is not a Thursday, and not | 
|  | 39                  * a Wednesday of a leap year, then this | 
|  | 40                  * year has only 52 weeks. */ | 
|  | 41                 int jan1 = (tm->tm_wday + 371U - tm->tm_yday) % 7; | 
|  | 42                 if (jan1 != 4 && (jan1 != 3 || !is_leap(tm->tm_year))) | 
|  | 43                         val = 1; | 
|  | 44         } | 
|  | 45         return val; | 
|  | 46 } | 
|  | 47 | 
|  | 48 const char *__tm_to_tzname(const struct tm *); | 
|  | 49 size_t __strftime_l(char *restrict, size_t, const char *restrict, const struct t
     m *restrict, locale_t); | 
|  | 50 | 
|  | 51 const char *__strftime_fmt_1(char (*s)[100], size_t *l, int f, const struct tm *
     tm, locale_t loc) | 
|  | 52 { | 
|  | 53         nl_item item; | 
|  | 54         long long val; | 
|  | 55         const char *fmt = "-"; | 
|  | 56         int width = 2; | 
|  | 57 | 
|  | 58         switch (f) { | 
|  | 59         case 'a': | 
|  | 60                 if (tm->tm_wday > 6U) goto string; | 
|  | 61                 item = ABDAY_1 + tm->tm_wday; | 
|  | 62                 goto nl_strcat; | 
|  | 63         case 'A': | 
|  | 64                 if (tm->tm_wday > 6U) goto string; | 
|  | 65                 item = DAY_1 + tm->tm_wday; | 
|  | 66                 goto nl_strcat; | 
|  | 67         case 'h': | 
|  | 68         case 'b': | 
|  | 69                 if (tm->tm_mon > 11U) goto string; | 
|  | 70                 item = ABMON_1 + tm->tm_mon; | 
|  | 71                 goto nl_strcat; | 
|  | 72         case 'B': | 
|  | 73                 if (tm->tm_mon > 11U) goto string; | 
|  | 74                 item = MON_1 + tm->tm_mon; | 
|  | 75                 goto nl_strcat; | 
|  | 76         case 'c': | 
|  | 77                 item = D_T_FMT; | 
|  | 78                 goto nl_strftime; | 
|  | 79         case 'C': | 
|  | 80                 val = (1900LL+tm->tm_year) / 100; | 
|  | 81                 goto number; | 
|  | 82         case 'd': | 
|  | 83                 val = tm->tm_mday; | 
|  | 84                 goto number; | 
|  | 85         case 'D': | 
|  | 86                 fmt = "%m/%d/%y"; | 
|  | 87                 goto recu_strftime; | 
|  | 88         case 'e': | 
|  | 89                 *l = snprintf(*s, sizeof *s, "%2d", tm->tm_mday); | 
|  | 90                 return *s; | 
|  | 91         case 'F': | 
|  | 92                 fmt = "%Y-%m-%d"; | 
|  | 93                 goto recu_strftime; | 
|  | 94         case 'g': | 
|  | 95         case 'G': | 
|  | 96                 val = tm->tm_year + 1900LL; | 
|  | 97                 if (tm->tm_yday < 3 && week_num(tm) != 1) val--; | 
|  | 98                 else if (tm->tm_yday > 360 && week_num(tm) == 1) val++; | 
|  | 99                 if (f=='g') val %= 100; | 
|  | 100                 else width = 4; | 
|  | 101                 goto number; | 
|  | 102         case 'H': | 
|  | 103                 val = tm->tm_hour; | 
|  | 104                 goto number; | 
|  | 105         case 'I': | 
|  | 106                 val = tm->tm_hour; | 
|  | 107                 if (!val) val = 12; | 
|  | 108                 else if (val > 12) val -= 12; | 
|  | 109                 goto number; | 
|  | 110         case 'j': | 
|  | 111                 val = tm->tm_yday+1; | 
|  | 112                 width = 3; | 
|  | 113                 goto number; | 
|  | 114         case 'm': | 
|  | 115                 val = tm->tm_mon+1; | 
|  | 116                 goto number; | 
|  | 117         case 'M': | 
|  | 118                 val = tm->tm_min; | 
|  | 119                 goto number; | 
|  | 120         case 'n': | 
|  | 121                 *l = 1; | 
|  | 122                 return "\n"; | 
|  | 123         case 'p': | 
|  | 124                 item = tm->tm_hour >= 12 ? PM_STR : AM_STR; | 
|  | 125                 goto nl_strcat; | 
|  | 126         case 'r': | 
|  | 127                 item = T_FMT_AMPM; | 
|  | 128                 goto nl_strftime; | 
|  | 129         case 'R': | 
|  | 130                 fmt = "%H:%M"; | 
|  | 131                 goto recu_strftime; | 
|  | 132         case 's': | 
|  | 133                 val = __tm_to_secs(tm) - tm->__tm_gmtoff; | 
|  | 134                 width = 1; | 
|  | 135                 goto number; | 
|  | 136         case 'S': | 
|  | 137                 val = tm->tm_sec; | 
|  | 138                 goto number; | 
|  | 139         case 't': | 
|  | 140                 *l = 1; | 
|  | 141                 return "\t"; | 
|  | 142         case 'T': | 
|  | 143                 fmt = "%H:%M:%S"; | 
|  | 144                 goto recu_strftime; | 
|  | 145         case 'u': | 
|  | 146                 val = tm->tm_wday ? tm->tm_wday : 7; | 
|  | 147                 width = 1; | 
|  | 148                 goto number; | 
|  | 149         case 'U': | 
|  | 150                 val = (tm->tm_yday + 7U - tm->tm_wday) / 7; | 
|  | 151                 goto number; | 
|  | 152         case 'W': | 
|  | 153                 val = (tm->tm_yday + 7U - (tm->tm_wday+6U)%7) / 7; | 
|  | 154                 goto number; | 
|  | 155         case 'V': | 
|  | 156                 val = week_num(tm); | 
|  | 157                 goto number; | 
|  | 158         case 'w': | 
|  | 159                 val = tm->tm_wday; | 
|  | 160                 width = 1; | 
|  | 161                 goto number; | 
|  | 162         case 'x': | 
|  | 163                 item = D_FMT; | 
|  | 164                 goto nl_strftime; | 
|  | 165         case 'X': | 
|  | 166                 item = T_FMT; | 
|  | 167                 goto nl_strftime; | 
|  | 168         case 'y': | 
|  | 169                 val = tm->tm_year % 100; | 
|  | 170                 goto number; | 
|  | 171         case 'Y': | 
|  | 172                 val = tm->tm_year + 1900LL; | 
|  | 173                 if (val >= 10000) { | 
|  | 174                         *l = snprintf(*s, sizeof *s, "+%lld", val); | 
|  | 175                         return *s; | 
|  | 176                 } | 
|  | 177                 width = 4; | 
|  | 178                 goto number; | 
|  | 179         case 'z': | 
|  | 180                 if (tm->tm_isdst < 0) { | 
|  | 181                         *l = 0; | 
|  | 182                         return ""; | 
|  | 183                 } | 
|  | 184                 *l = snprintf(*s, sizeof *s, "%+.2d%.2d", | 
|  | 185                         (tm->__tm_gmtoff)/3600, | 
|  | 186                         abs(tm->__tm_gmtoff%3600)/60); | 
|  | 187                 return *s; | 
|  | 188         case 'Z': | 
|  | 189                 if (tm->tm_isdst < 0) { | 
|  | 190                         *l = 0; | 
|  | 191                         return ""; | 
|  | 192                 } | 
|  | 193                 fmt = __tm_to_tzname(tm); | 
|  | 194                 goto string; | 
|  | 195         case '%': | 
|  | 196                 *l = 1; | 
|  | 197                 return "%"; | 
|  | 198         default: | 
|  | 199                 return 0; | 
|  | 200         } | 
|  | 201 number: | 
|  | 202         *l = snprintf(*s, sizeof *s, "%0*lld", width, val); | 
|  | 203         return *s; | 
|  | 204 nl_strcat: | 
|  | 205         fmt = __nl_langinfo_l(item, loc); | 
|  | 206 string: | 
|  | 207         *l = strlen(fmt); | 
|  | 208         return fmt; | 
|  | 209 nl_strftime: | 
|  | 210         fmt = __nl_langinfo_l(item, loc); | 
|  | 211 recu_strftime: | 
|  | 212         *l = __strftime_l(*s, sizeof *s, fmt, tm, loc); | 
|  | 213         if (!*l) return 0; | 
|  | 214         return *s; | 
|  | 215 } | 
|  | 216 | 
|  | 217 size_t __strftime_l(char *restrict s, size_t n, const char *restrict f, const st
     ruct tm *restrict tm, locale_t loc) | 
|  | 218 { | 
|  | 219         size_t l, k; | 
|  | 220         char buf[100]; | 
|  | 221         char *p; | 
|  | 222         const char *t; | 
|  | 223         int plus; | 
|  | 224         unsigned long width; | 
|  | 225         for (l=0; l<n; f++) { | 
|  | 226                 if (!*f) { | 
|  | 227                         s[l] = 0; | 
|  | 228                         return l; | 
|  | 229                 } | 
|  | 230                 if (*f != '%') { | 
|  | 231                         s[l++] = *f; | 
|  | 232                         continue; | 
|  | 233                 } | 
|  | 234                 f++; | 
|  | 235                 if ((plus = (*f == '+'))) f++; | 
|  | 236                 width = strtoul(f, &p, 10); | 
|  | 237                 if (*p == 'C' || *p == 'F' || *p == 'G' || *p == 'Y') { | 
|  | 238                         if (!width && p!=f) width = 1; | 
|  | 239                 } else { | 
|  | 240                         width = 0; | 
|  | 241                 } | 
|  | 242                 f = p; | 
|  | 243                 if (*f == 'E' || *f == 'O') f++; | 
|  | 244                 t = __strftime_fmt_1(&buf, &k, *f, tm, loc); | 
|  | 245                 if (!t) break; | 
|  | 246                 if (width) { | 
|  | 247                         for (; *t=='+' || *t=='-' || (*t=='0'&&t[1]); t++, k--); | 
|  | 248                         width--; | 
|  | 249                         if (plus && tm->tm_year >= 10000-1900) | 
|  | 250                                 s[l++] = '+'; | 
|  | 251                         else if (tm->tm_year < -1900) | 
|  | 252                                 s[l++] = '-'; | 
|  | 253                         else | 
|  | 254                                 width++; | 
|  | 255                         for (; width > k && l < n; width--) | 
|  | 256                                 s[l++] = '0'; | 
|  | 257                 } | 
|  | 258                 if (k > n-l) k = n-l; | 
|  | 259                 memcpy(s+l, t, k); | 
|  | 260                 l += k; | 
|  | 261         } | 
|  | 262         if (n) { | 
|  | 263                 if (l==n) l=n-1; | 
|  | 264                 s[l] = 0; | 
|  | 265         } | 
|  | 266         return 0; | 
|  | 267 } | 
|  | 268 | 
|  | 269 size_t strftime(char *restrict s, size_t n, const char *restrict f, const struct
      tm *restrict tm) | 
|  | 270 { | 
|  | 271         return __strftime_l(s, n, f, tm, CURRENT_LOCALE); | 
|  | 272 } | 
|  | 273 | 
|  | 274 weak_alias(__strftime_l, strftime_l); | 
| OLD | NEW | 
|---|