remove gcc34
[dragonfly.git] / crypto / heimdal-0.6.3 / lib / roken / strftime.c
blob985b38aa7d7837524f1e5d0db11e70b3e392d022
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 #ifdef HAVE_CONFIG_H
34 #include <config.h>
35 #endif
36 #include "roken.h"
38 RCSID("$Id: strftime.c,v 1.13 2002/08/20 12:42:37 joda Exp $");
40 static const char *abb_weekdays[] = {
41 "Sun",
42 "Mon",
43 "Tue",
44 "Wed",
45 "Thu",
46 "Fri",
47 "Sat",
50 static const char *full_weekdays[] = {
51 "Sunday",
52 "Monday",
53 "Tuesday",
54 "Wednesday",
55 "Thursday",
56 "Friday",
57 "Saturday",
60 static const char *abb_month[] = {
61 "Jan",
62 "Feb",
63 "Mar",
64 "Apr",
65 "May",
66 "Jun",
67 "Jul",
68 "Aug",
69 "Sep",
70 "Oct",
71 "Nov",
72 "Dec"
75 static const char *full_month[] = {
76 "January",
77 "February",
78 "Mars",
79 "April",
80 "May",
81 "June",
82 "July",
83 "August",
84 "September",
85 "October",
86 "November",
87 "December"
90 static const char *ampm[] = {
91 "AM",
92 "PM"
96 * Convert hour in [0, 24] to [12 1 - 11 12 1 - 11 12]
99 static int
100 hour_24to12 (int hour)
102 int ret = hour % 12;
104 if (ret == 0)
105 ret = 12;
106 return ret;
110 * Return AM or PM for `hour'
113 static const char *
114 hour_to_ampm (int hour)
116 return ampm[hour / 12];
120 * Return the week number of `tm' (Sunday being the first day of the week)
121 * as [0, 53]
124 static int
125 week_number_sun (const struct tm *tm)
127 return (tm->tm_yday + 7 - (tm->tm_yday % 7 - tm->tm_wday + 7) % 7) / 7;
131 * Return the week number of `tm' (Monday being the first day of the week)
132 * as [0, 53]
135 static int
136 week_number_mon (const struct tm *tm)
138 int wday = (tm->tm_wday + 6) % 7;
140 return (tm->tm_yday + 7 - (tm->tm_yday % 7 - wday + 7) % 7) / 7;
144 * Return the week number of `tm' (Monday being the first day of the
145 * week) as [01, 53]. Week number one is the one that has four or more
146 * days in that year.
149 static int
150 week_number_mon4 (const struct tm *tm)
152 int wday = (tm->tm_wday + 6) % 7;
153 int w1day = (wday - tm->tm_yday % 7 + 7) % 7;
154 int ret;
156 ret = (tm->tm_yday + w1day) / 7;
157 if (w1day >= 4)
158 --ret;
159 if (ret == -1)
160 ret = 53;
161 else
162 ++ret;
163 return ret;
170 size_t
171 strftime (char *buf, size_t maxsize, const char *format,
172 const struct tm *tm)
174 size_t n = 0;
175 int ret;
177 while (*format != '\0' && n < maxsize) {
178 if (*format == '%') {
179 ++format;
180 if(*format == 'E' || *format == 'O')
181 ++format;
182 switch (*format) {
183 case 'a' :
184 ret = snprintf (buf, maxsize - n,
185 "%s", abb_weekdays[tm->tm_wday]);
186 break;
187 case 'A' :
188 ret = snprintf (buf, maxsize - n,
189 "%s", full_weekdays[tm->tm_wday]);
190 break;
191 case 'h' :
192 case 'b' :
193 ret = snprintf (buf, maxsize - n,
194 "%s", abb_month[tm->tm_mon]);
195 break;
196 case 'B' :
197 ret = snprintf (buf, maxsize - n,
198 "%s", full_month[tm->tm_mon]);
199 break;
200 case 'c' :
201 ret = snprintf (buf, maxsize - n,
202 "%d:%02d:%02d %02d:%02d:%02d",
203 tm->tm_year,
204 tm->tm_mon + 1,
205 tm->tm_mday,
206 tm->tm_hour,
207 tm->tm_min,
208 tm->tm_sec);
209 break;
210 case 'C' :
211 ret = snprintf (buf, maxsize - n,
212 "%02d", (tm->tm_year + 1900) / 100);
213 break;
214 case 'd' :
215 ret = snprintf (buf, maxsize - n,
216 "%02d", tm->tm_mday);
217 break;
218 case 'D' :
219 ret = snprintf (buf, maxsize - n,
220 "%02d/%02d/%02d",
221 tm->tm_mon + 1,
222 tm->tm_mday,
223 (tm->tm_year + 1900) % 100);
224 break;
225 case 'e' :
226 ret = snprintf (buf, maxsize - n,
227 "%2d", tm->tm_mday);
228 break;
229 case 'F':
230 ret = snprintf (buf, maxsize - n,
231 "%04d-%02d-%02d", tm->tm_year + 1900,
232 tm->tm_mon + 1, tm->tm_mday);
233 break;
234 case 'g':
235 /* last two digits of week-based year */
236 abort();
237 case 'G':
238 /* week-based year */
239 abort();
240 case 'H' :
241 ret = snprintf (buf, maxsize - n,
242 "%02d", tm->tm_hour);
243 break;
244 case 'I' :
245 ret = snprintf (buf, maxsize - n,
246 "%02d",
247 hour_24to12 (tm->tm_hour));
248 break;
249 case 'j' :
250 ret = snprintf (buf, maxsize - n,
251 "%03d", tm->tm_yday + 1);
252 break;
253 case 'k' :
254 ret = snprintf (buf, maxsize - n,
255 "%2d", tm->tm_hour);
256 break;
257 case 'l' :
258 ret = snprintf (buf, maxsize - n,
259 "%2d",
260 hour_24to12 (tm->tm_hour));
261 break;
262 case 'm' :
263 ret = snprintf (buf, maxsize - n,
264 "%02d", tm->tm_mon + 1);
265 break;
266 case 'M' :
267 ret = snprintf (buf, maxsize - n,
268 "%02d", tm->tm_min);
269 break;
270 case 'n' :
271 ret = snprintf (buf, maxsize - n, "\n");
272 break;
273 case 'p' :
274 ret = snprintf (buf, maxsize - n, "%s",
275 hour_to_ampm (tm->tm_hour));
276 break;
277 case 'r' :
278 ret = snprintf (buf, maxsize - n,
279 "%02d:%02d:%02d %s",
280 hour_24to12 (tm->tm_hour),
281 tm->tm_min,
282 tm->tm_sec,
283 hour_to_ampm (tm->tm_hour));
284 break;
285 case 'R' :
286 ret = snprintf (buf, maxsize - n,
287 "%02d:%02d",
288 tm->tm_hour,
289 tm->tm_min);
291 case 's' :
292 ret = snprintf (buf, maxsize - n,
293 "%d", (int)mktime((struct tm *)tm));
294 break;
295 case 'S' :
296 ret = snprintf (buf, maxsize - n,
297 "%02d", tm->tm_sec);
298 break;
299 case 't' :
300 ret = snprintf (buf, maxsize - n, "\t");
301 break;
302 case 'T' :
303 case 'X' :
304 ret = snprintf (buf, maxsize - n,
305 "%02d:%02d:%02d",
306 tm->tm_hour,
307 tm->tm_min,
308 tm->tm_sec);
309 break;
310 case 'u' :
311 ret = snprintf (buf, maxsize - n,
312 "%d", (tm->tm_wday == 0) ? 7 : tm->tm_wday);
313 break;
314 case 'U' :
315 ret = snprintf (buf, maxsize - n,
316 "%02d", week_number_sun (tm));
317 break;
318 case 'V' :
319 ret = snprintf (buf, maxsize - n,
320 "%02d", week_number_mon4 (tm));
321 break;
322 case 'w' :
323 ret = snprintf (buf, maxsize - n,
324 "%d", tm->tm_wday);
325 break;
326 case 'W' :
327 ret = snprintf (buf, maxsize - n,
328 "%02d", week_number_mon (tm));
329 break;
330 case 'x' :
331 ret = snprintf (buf, maxsize - n,
332 "%d:%02d:%02d",
333 tm->tm_year,
334 tm->tm_mon + 1,
335 tm->tm_mday);
336 break;
337 case 'y' :
338 ret = snprintf (buf, maxsize - n,
339 "%02d", (tm->tm_year + 1900) % 100);
340 break;
341 case 'Y' :
342 ret = snprintf (buf, maxsize - n,
343 "%d", tm->tm_year + 1900);
344 break;
345 case 'z':
346 ret = snprintf (buf, maxsize - n,
347 "%ld",
348 #if defined(HAVE_STRUCT_TM_TM_GMTOFF)
349 (long)tm->tm_gmtoff
350 #elif defined(HAVE_TIMEZONE)
351 #ifdef HAVE_ALTZONE
352 tm->tm_isdst ?
353 (long)altzone :
354 #endif
355 (long)timezone
356 #else
357 #error Where in timezone chaos are you?
358 #endif
360 break;
361 case 'Z' :
362 ret = snprintf (buf, maxsize - n,
363 "%s",
365 #if defined(HAVE_STRUCT_TM_TM_ZONE)
366 tm->tm_zone
367 #elif defined(HAVE_TIMEZONE)
368 tzname[tm->tm_isdst]
369 #else
370 #error what?
371 #endif
373 break;
374 case '\0' :
375 --format;
376 /* FALLTHROUGH */
377 case '%' :
378 ret = snprintf (buf, maxsize - n,
379 "%%");
380 break;
381 default :
382 ret = snprintf (buf, maxsize - n,
383 "%%%c", *format);
384 break;
386 if (ret < 0 || ret >= maxsize - n)
387 return 0;
388 n += ret;
389 buf += ret;
390 ++format;
391 } else {
392 *buf++ = *format++;
393 ++n;
396 *buf++ = '\0';
397 return n;