lib/gssapi/krb5: implement GSS_C_CHANNEL_BOUND_FLAG for gss_init_sec_context()
[heimdal.git] / lib / roken / strftime.c
blob7be930755cad2c76b35808e7419afc2783a7cc2b
1 /*
2 * Copyright (c) 1999 - 2002 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of KTH nor the names of its contributors may be
18 * used to endorse or promote products derived from this software without
19 * specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY
22 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE
25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
28 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
31 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
33 #include <config.h>
34 #include "roken.h"
35 #ifdef TEST_STRPFTIME
36 #include "strpftime-test.h"
37 #endif
39 #if defined(_WIN32)
40 # define timezone _timezone
41 # define tzname _tzname
42 #endif
44 static const char *abb_weekdays[] = {
45 "Sun",
46 "Mon",
47 "Tue",
48 "Wed",
49 "Thu",
50 "Fri",
51 "Sat",
54 static const char *full_weekdays[] = {
55 "Sunday",
56 "Monday",
57 "Tuesday",
58 "Wednesday",
59 "Thursday",
60 "Friday",
61 "Saturday",
64 static const char *abb_month[] = {
65 "Jan",
66 "Feb",
67 "Mar",
68 "Apr",
69 "May",
70 "Jun",
71 "Jul",
72 "Aug",
73 "Sep",
74 "Oct",
75 "Nov",
76 "Dec"
79 static const char *full_month[] = {
80 "January",
81 "February",
82 "Mars",
83 "April",
84 "May",
85 "June",
86 "July",
87 "August",
88 "September",
89 "October",
90 "November",
91 "December"
94 static const char *ampm[] = {
95 "AM",
96 "PM"
100 * Convert hour in [0, 24] to [12 1 - 11 12 1 - 11 12]
103 static int
104 hour_24to12 (int hour)
106 int ret = hour % 12;
108 if (ret == 0)
109 ret = 12;
110 return ret;
114 * Return AM or PM for `hour'
117 static const char *
118 hour_to_ampm (int hour)
120 return ampm[hour / 12];
124 * Return the week number of `tm' (Sunday being the first day of the week)
125 * as [0, 53]
128 static int
129 week_number_sun (const struct tm *tm)
131 return (tm->tm_yday + 7 - (tm->tm_yday % 7 - tm->tm_wday + 7) % 7) / 7;
135 * Return the week number of `tm' (Monday being the first day of the week)
136 * as [0, 53]
139 static int
140 week_number_mon (const struct tm *tm)
142 int wday = (tm->tm_wday + 6) % 7;
144 return (tm->tm_yday + 7 - (tm->tm_yday % 7 - wday + 7) % 7) / 7;
148 * Return the week number of `tm' (Monday being the first day of the
149 * week) as [01, 53]. Week number one is the one that has four or more
150 * days in that year.
153 static int
154 week_number_mon4 (const struct tm *tm)
156 int wday = (tm->tm_wday + 6) % 7;
157 int w1day = (wday - tm->tm_yday % 7 + 7) % 7;
158 int ret;
160 ret = (tm->tm_yday + w1day) / 7;
161 if (w1day >= 4)
162 --ret;
163 if (ret == -1)
164 ret = 53;
165 else
166 ++ret;
167 return ret;
174 ROKEN_LIB_FUNCTION size_t ROKEN_LIB_CALL
175 strftime (char *buf, size_t maxsize, const char *format,
176 const struct tm *tm)
178 size_t n = 0;
179 int ret;
181 while (*format != '\0' && n < maxsize) {
182 if (*format == '%') {
183 ++format;
184 if(*format == 'E' || *format == 'O')
185 ++format;
186 switch (*format) {
187 case 'a' :
188 ret = snprintf (buf, maxsize - n,
189 "%s", abb_weekdays[tm->tm_wday]);
190 break;
191 case 'A' :
192 ret = snprintf (buf, maxsize - n,
193 "%s", full_weekdays[tm->tm_wday]);
194 break;
195 case 'h' :
196 case 'b' :
197 ret = snprintf (buf, maxsize - n,
198 "%s", abb_month[tm->tm_mon]);
199 break;
200 case 'B' :
201 ret = snprintf (buf, maxsize - n,
202 "%s", full_month[tm->tm_mon]);
203 break;
204 case 'c' :
205 ret = snprintf (buf, maxsize - n,
206 "%d:%02d:%02d %02d:%02d:%02d",
207 tm->tm_year,
208 tm->tm_mon + 1,
209 tm->tm_mday,
210 tm->tm_hour,
211 tm->tm_min,
212 tm->tm_sec);
213 break;
214 case 'C' :
215 ret = snprintf (buf, maxsize - n,
216 "%02d", (tm->tm_year + 1900) / 100);
217 break;
218 case 'd' :
219 ret = snprintf (buf, maxsize - n,
220 "%02d", tm->tm_mday);
221 break;
222 case 'D' :
223 ret = snprintf (buf, maxsize - n,
224 "%02d/%02d/%02d",
225 tm->tm_mon + 1,
226 tm->tm_mday,
227 (tm->tm_year + 1900) % 100);
228 break;
229 case 'e' :
230 ret = snprintf (buf, maxsize - n,
231 "%2d", tm->tm_mday);
232 break;
233 case 'F':
234 ret = snprintf (buf, maxsize - n,
235 "%04d-%02d-%02d", tm->tm_year + 1900,
236 tm->tm_mon + 1, tm->tm_mday);
237 break;
238 case 'g':
239 /* last two digits of week-based year */
240 abort();
241 case 'G':
242 /* week-based year */
243 abort();
244 case 'H' :
245 ret = snprintf (buf, maxsize - n,
246 "%02d", tm->tm_hour);
247 break;
248 case 'I' :
249 ret = snprintf (buf, maxsize - n,
250 "%02d",
251 hour_24to12 (tm->tm_hour));
252 break;
253 case 'j' :
254 ret = snprintf (buf, maxsize - n,
255 "%03d", tm->tm_yday + 1);
256 break;
257 case 'k' :
258 ret = snprintf (buf, maxsize - n,
259 "%2d", tm->tm_hour);
260 break;
261 case 'l' :
262 ret = snprintf (buf, maxsize - n,
263 "%2d",
264 hour_24to12 (tm->tm_hour));
265 break;
266 case 'm' :
267 ret = snprintf (buf, maxsize - n,
268 "%02d", tm->tm_mon + 1);
269 break;
270 case 'M' :
271 ret = snprintf (buf, maxsize - n,
272 "%02d", tm->tm_min);
273 break;
274 case 'n' :
275 ret = snprintf (buf, maxsize - n, "\n");
276 break;
277 case 'p' :
278 ret = snprintf (buf, maxsize - n, "%s",
279 hour_to_ampm (tm->tm_hour));
280 break;
281 case 'r' :
282 ret = snprintf (buf, maxsize - n,
283 "%02d:%02d:%02d %s",
284 hour_24to12 (tm->tm_hour),
285 tm->tm_min,
286 tm->tm_sec,
287 hour_to_ampm (tm->tm_hour));
288 break;
289 case 'R' :
290 ret = snprintf (buf, maxsize - n,
291 "%02d:%02d",
292 tm->tm_hour,
293 tm->tm_min);
294 break;
295 case 's' :
296 ret = snprintf (buf, maxsize - n,
297 "%d", (int)mktime(rk_UNCONST(tm)));
298 break;
299 case 'S' :
300 ret = snprintf (buf, maxsize - n,
301 "%02d", tm->tm_sec);
302 break;
303 case 't' :
304 ret = snprintf (buf, maxsize - n, "\t");
305 break;
306 case 'T' :
307 case 'X' :
308 ret = snprintf (buf, maxsize - n,
309 "%02d:%02d:%02d",
310 tm->tm_hour,
311 tm->tm_min,
312 tm->tm_sec);
313 break;
314 case 'u' :
315 ret = snprintf (buf, maxsize - n,
316 "%d", (tm->tm_wday == 0) ? 7 : tm->tm_wday);
317 break;
318 case 'U' :
319 ret = snprintf (buf, maxsize - n,
320 "%02d", week_number_sun (tm));
321 break;
322 case 'V' :
323 ret = snprintf (buf, maxsize - n,
324 "%02d", week_number_mon4 (tm));
325 break;
326 case 'w' :
327 ret = snprintf (buf, maxsize - n,
328 "%d", tm->tm_wday);
329 break;
330 case 'W' :
331 ret = snprintf (buf, maxsize - n,
332 "%02d", week_number_mon (tm));
333 break;
334 case 'x' :
335 ret = snprintf (buf, maxsize - n,
336 "%d:%02d:%02d",
337 tm->tm_year,
338 tm->tm_mon + 1,
339 tm->tm_mday);
340 break;
341 case 'y' :
342 ret = snprintf (buf, maxsize - n,
343 "%02d", (tm->tm_year + 1900) % 100);
344 break;
345 case 'Y' :
346 ret = snprintf (buf, maxsize - n,
347 "%d", tm->tm_year + 1900);
348 break;
349 case 'z':
350 ret = snprintf (buf, maxsize - n,
351 "%ld",
352 #if defined(HAVE_STRUCT_TM_TM_GMTOFF)
353 (long)tm->tm_gmtoff
354 #elif defined(HAVE_TIMEZONE)
355 #ifdef HAVE_ALTZONE
356 tm->tm_isdst ?
357 (long)altzone :
358 #endif
359 (long)timezone
360 #else
361 #error Where in timezone chaos are you?
362 #endif
364 break;
365 case 'Z' :
366 ret = snprintf (buf, maxsize - n,
367 "%s",
369 #if defined(HAVE_STRUCT_TM_TM_ZONE)
370 tm->tm_zone
371 #elif defined(HAVE_TIMEZONE)
372 tzname[tm->tm_isdst]
373 #else
374 #error what?
375 #endif
377 break;
378 case '\0' :
379 --format;
380 HEIM_FALLTHROUGH;
381 case '%' :
382 ret = snprintf (buf, maxsize - n,
383 "%%");
384 break;
385 default :
386 ret = snprintf (buf, maxsize - n,
387 "%%%c", *format);
388 break;
390 if (ret < 0 || ret >= (int)(maxsize - n))
391 return 0;
392 n += ret;
393 buf += ret;
394 ++format;
395 } else {
396 *buf++ = *format++;
397 ++n;
400 *buf = '\0';
401 return n;