]>
Commit | Line | Data |
---|---|---|
2aa62f2b | 1 | /** @file\r |
2 | Implementation of the strftime function for <time.h>.\r | |
3 | \r | |
4 | Based on the UCB version with the ID appearing below.\r | |
5 | This is ANSIish only when "multibyte character == plain character".\r | |
6 | \r | |
7 | Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>\r | |
8 | This program and the accompanying materials are licensed and made available under\r | |
9 | the terms and conditions of the BSD License that accompanies this distribution.\r | |
10 | The full text of the license may be found at\r | |
11 | http://opensource.org/licenses/bsd-license.php.\r | |
12 | \r | |
13 | THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r | |
14 | WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r | |
15 | \r | |
16 | Copyright (c) 1989, 1993\r | |
17 | The Regents of the University of California. All rights reserved.\r | |
18 | \r | |
19 | Redistribution and use in source and binary forms, with or without\r | |
20 | modification, are permitted provided that the following conditions\r | |
21 | are met:\r | |
22 | 1. Redistributions of source code must retain the above copyright\r | |
23 | notice, this list of conditions and the following disclaimer.\r | |
24 | 2. Redistributions in binary form must reproduce the above copyright\r | |
25 | notice, this list of conditions and the following disclaimer in the\r | |
26 | documentation and/or other materials provided with the distribution.\r | |
27 | 3. All advertising materials mentioning features or use of this software\r | |
28 | must display the following acknowledgement:\r | |
29 | This product includes software developed by the University of\r | |
30 | California, Berkeley and its contributors.\r | |
31 | 4. Neither the name of the University nor the names of its contributors\r | |
32 | may be used to endorse or promote products derived from this software\r | |
33 | without specific prior written permission.\r | |
34 | \r | |
35 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND\r | |
36 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r | |
37 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\r | |
38 | ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE\r | |
39 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\r | |
40 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\r | |
41 | OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r | |
42 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\r | |
43 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\r | |
44 | OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\r | |
45 | SUCH DAMAGE.\r | |
46 | \r | |
47 | NetBSD: strftime.c,v 1.17.4.1 2007/08/21 20:08:21 liamjfoy Exp\r | |
48 | **/\r | |
49 | #include <LibConfig.h>\r | |
50 | #include <sys/EfiCdefs.h>\r | |
51 | \r | |
52 | #include "namespace.h"\r | |
53 | #include <time.h>\r | |
54 | #include "tzfile.h"\r | |
53e1e5c6 | 55 | #include "TimeVals.h"\r |
2aa62f2b | 56 | #include "fcntl.h"\r |
57 | #include "locale.h"\r | |
58 | \r | |
59 | #include "sys/localedef.h"\r | |
60 | #include <MainData.h>\r | |
61 | \r | |
62 | /*\r | |
63 | ** We don't use these extensions in strftime operation even when\r | |
64 | ** supported by the local tzcode configuration. A strictly\r | |
65 | ** conforming C application may leave them in undefined state.\r | |
66 | */\r | |
67 | \r | |
68 | #ifdef _LIBC\r | |
69 | #undef TM_ZONE\r | |
70 | #undef TM_GMTOFF\r | |
71 | #endif\r | |
72 | \r | |
73 | #define Locale _CurrentTimeLocale\r | |
74 | \r | |
d7ce7006 | 75 | static char * _add(const char *, char *, const char * const);\r |
76 | static char * _conv(const int, const char * const, char * const, const char * const);\r | |
77 | static char * _fmt(const char *, const struct tm * const, char *, const char * const, int *);\r | |
2aa62f2b | 78 | \r |
79 | #define NO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU\r | |
80 | \r | |
81 | #ifndef YEAR_2000_NAME\r | |
82 | #define YEAR_2000_NAME "CHECK_STRFTIME_FORMATS_FOR_TWO_DIGIT_YEARS"\r | |
83 | #endif /* !defined YEAR_2000_NAME */\r | |
84 | \r | |
85 | \r | |
86 | #define IN_NONE 0\r | |
87 | #define IN_SOME 1\r | |
88 | #define IN_THIS 2\r | |
89 | #define IN_ALL 3\r | |
90 | \r | |
91 | size_t\r | |
2aa62f2b | 92 | strftime(\r |
93 | char * __restrict s,\r | |
94 | size_t maxsize,\r | |
95 | const char * __restrict format,\r | |
96 | const struct tm * __restrict timeptr\r | |
97 | )\r | |
98 | {\r | |
99 | char * p;\r | |
100 | int warn;\r | |
101 | \r | |
102 | tzset();\r | |
103 | warn = IN_NONE;\r | |
104 | p = _fmt(((format == NULL) ? "%c" : format), timeptr, s, s + maxsize, &warn);\r | |
105 | \r | |
106 | #ifndef NO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU\r | |
107 | if (warn != IN_NONE && getenv(YEAR_2000_NAME) != NULL) {\r | |
108 | (void) fprintf(stderr, "\n");\r | |
109 | if (format == NULL)\r | |
110 | (void) fprintf(stderr, "NULL strftime format ");\r | |
111 | else (void) fprintf(stderr, "strftime format \"%s\" ",\r | |
112 | format);\r | |
113 | (void) fprintf(stderr, "yields only two digits of years in ");\r | |
114 | if (warn == IN_SOME)\r | |
115 | (void) fprintf(stderr, "some locales");\r | |
116 | else if (warn == IN_THIS)\r | |
117 | (void) fprintf(stderr, "the current locale");\r | |
118 | else (void) fprintf(stderr, "all locales");\r | |
119 | (void) fprintf(stderr, "\n");\r | |
120 | }\r | |
121 | #endif /* !defined NO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU */\r | |
122 | \r | |
123 | if (p == s + maxsize)\r | |
124 | return 0;\r | |
125 | *p = '\0';\r | |
126 | return p - s;\r | |
127 | }\r | |
128 | \r | |
129 | static char *\r | |
2aa62f2b | 130 | _fmt(\r |
131 | const char * format,\r | |
132 | const struct tm * const t,\r | |
133 | char * pt,\r | |
134 | const char * const ptlim,\r | |
135 | int * warnp\r | |
136 | )\r | |
137 | {\r | |
138 | for ( ; *format; ++format) {\r | |
139 | if (*format == '%') {\r | |
140 | label:\r | |
141 | switch (*++format) {\r | |
142 | case '\0':\r | |
143 | --format;\r | |
144 | break;\r | |
145 | case 'A':\r | |
146 | pt = _add((t->tm_wday < 0 ||\r | |
147 | t->tm_wday >= DAYSPERWEEK) ?\r | |
148 | "?" : Locale->day[t->tm_wday],\r | |
149 | pt, ptlim);\r | |
150 | continue;\r | |
151 | case 'a':\r | |
152 | pt = _add((t->tm_wday < 0 ||\r | |
153 | t->tm_wday >= DAYSPERWEEK) ?\r | |
154 | "?" : Locale->abday[t->tm_wday],\r | |
155 | pt, ptlim);\r | |
156 | continue;\r | |
157 | case 'B':\r | |
158 | pt = _add((t->tm_mon < 0 ||\r | |
159 | t->tm_mon >= MONSPERYEAR) ?\r | |
160 | "?" : Locale->mon[t->tm_mon],\r | |
161 | pt, ptlim);\r | |
162 | continue;\r | |
163 | case 'b':\r | |
164 | case 'h':\r | |
165 | pt = _add((t->tm_mon < 0 ||\r | |
166 | t->tm_mon >= MONSPERYEAR) ?\r | |
167 | "?" : Locale->abmon[t->tm_mon],\r | |
168 | pt, ptlim);\r | |
169 | continue;\r | |
170 | case 'C':\r | |
171 | /*\r | |
172 | ** %C used to do a...\r | |
173 | ** _fmt("%a %b %e %X %Y", t);\r | |
174 | ** ...whereas now POSIX 1003.2 calls for\r | |
175 | ** something completely different.\r | |
176 | ** (ado, 1993-05-24)\r | |
177 | */\r | |
178 | pt = _conv((t->tm_year + TM_YEAR_BASE) / 100,\r | |
179 | "%02d", pt, ptlim);\r | |
180 | continue;\r | |
181 | case 'c':\r | |
182 | {\r | |
183 | int warn2 = IN_SOME;\r | |
184 | \r | |
185 | pt = _fmt(Locale->d_t_fmt, t, pt, ptlim, &warn2);\r | |
186 | if (warn2 == IN_ALL)\r | |
187 | warn2 = IN_THIS;\r | |
188 | if (warn2 > *warnp)\r | |
189 | *warnp = warn2;\r | |
190 | }\r | |
191 | continue;\r | |
192 | case 'D':\r | |
193 | pt = _fmt("%m/%d/%y", t, pt, ptlim, warnp);\r | |
194 | continue;\r | |
195 | case 'd':\r | |
196 | pt = _conv(t->tm_mday, "%02d", pt, ptlim);\r | |
197 | continue;\r | |
198 | case 'E':\r | |
199 | case 'O':\r | |
200 | /*\r | |
201 | ** C99 locale modifiers.\r | |
202 | ** The sequences\r | |
203 | ** %Ec %EC %Ex %EX %Ey %EY\r | |
204 | ** %Od %oe %OH %OI %Om %OM\r | |
205 | ** %OS %Ou %OU %OV %Ow %OW %Oy\r | |
206 | ** are supposed to provide alternate\r | |
207 | ** representations.\r | |
208 | */\r | |
209 | goto label;\r | |
210 | case 'e':\r | |
211 | pt = _conv(t->tm_mday, "%2d", pt, ptlim);\r | |
212 | continue;\r | |
213 | case 'F':\r | |
214 | pt = _fmt("%Y-%m-%d", t, pt, ptlim, warnp);\r | |
215 | continue;\r | |
216 | case 'H':\r | |
217 | pt = _conv(t->tm_hour, "%02d", pt, ptlim);\r | |
218 | continue;\r | |
219 | case 'I':\r | |
220 | pt = _conv((t->tm_hour % 12) ?\r | |
221 | (t->tm_hour % 12) : 12,\r | |
222 | "%02d", pt, ptlim);\r | |
223 | continue;\r | |
224 | case 'j':\r | |
225 | pt = _conv(t->tm_yday + 1, "%03d", pt, ptlim);\r | |
226 | continue;\r | |
227 | case 'k':\r | |
228 | /*\r | |
229 | ** This used to be...\r | |
230 | ** _conv(t->tm_hour % 12 ?\r | |
231 | ** t->tm_hour % 12 : 12, 2, ' ');\r | |
232 | ** ...and has been changed to the below to\r | |
233 | ** match SunOS 4.1.1 and Arnold Robbins'\r | |
234 | ** strftime version 3.0. That is, "%k" and\r | |
235 | ** "%l" have been swapped.\r | |
236 | ** (ado, 1993-05-24)\r | |
237 | */\r | |
238 | pt = _conv(t->tm_hour, "%2d", pt, ptlim);\r | |
239 | continue;\r | |
240 | #ifdef KITCHEN_SINK\r | |
241 | case 'K':\r | |
242 | /*\r | |
243 | ** After all this time, still unclaimed!\r | |
244 | */\r | |
245 | pt = _add("kitchen sink", pt, ptlim);\r | |
246 | continue;\r | |
247 | #endif /* defined KITCHEN_SINK */\r | |
248 | case 'l':\r | |
249 | /*\r | |
250 | ** This used to be...\r | |
251 | ** _conv(t->tm_hour, 2, ' ');\r | |
252 | ** ...and has been changed to the below to\r | |
253 | ** match SunOS 4.1.1 and Arnold Robbin's\r | |
254 | ** strftime version 3.0. That is, "%k" and\r | |
255 | ** "%l" have been swapped.\r | |
256 | ** (ado, 1993-05-24)\r | |
257 | */\r | |
258 | pt = _conv((t->tm_hour % 12) ?\r | |
259 | (t->tm_hour % 12) : 12,\r | |
260 | "%2d", pt, ptlim);\r | |
261 | continue;\r | |
262 | case 'M':\r | |
263 | pt = _conv(t->tm_min, "%02d", pt, ptlim);\r | |
264 | continue;\r | |
265 | case 'm':\r | |
266 | pt = _conv(t->tm_mon + 1, "%02d", pt, ptlim);\r | |
267 | continue;\r | |
268 | case 'n':\r | |
269 | pt = _add("\n", pt, ptlim);\r | |
270 | continue;\r | |
271 | case 'p':\r | |
272 | pt = _add((t->tm_hour >= (HOURSPERDAY / 2)) ?\r | |
273 | Locale->am_pm[1] :\r | |
274 | Locale->am_pm[0],\r | |
275 | pt, ptlim);\r | |
276 | continue;\r | |
277 | case 'R':\r | |
278 | pt = _fmt("%H:%M", t, pt, ptlim, warnp);\r | |
279 | continue;\r | |
280 | case 'r':\r | |
281 | pt = _fmt(Locale->t_fmt_ampm, t, pt, ptlim,\r | |
282 | warnp);\r | |
283 | continue;\r | |
284 | case 'S':\r | |
285 | pt = _conv(t->tm_sec, "%02d", pt, ptlim);\r | |
286 | continue;\r | |
287 | case 's':\r | |
288 | {\r | |
289 | struct tm tm;\r | |
290 | char buf[INT_STRLEN_MAXIMUM(\r | |
291 | time_t) + 1];\r | |
292 | time_t mkt;\r | |
293 | \r | |
294 | tm = *t;\r | |
295 | mkt = mktime(&tm);\r | |
296 | /* CONSTCOND */\r | |
297 | if (TYPE_SIGNED(time_t))\r | |
298 | (void) sprintf(buf, "%ld",\r | |
299 | (long) mkt);\r | |
300 | else (void) sprintf(buf, "%lu",\r | |
301 | (unsigned long) mkt);\r | |
302 | pt = _add(buf, pt, ptlim);\r | |
303 | }\r | |
304 | continue;\r | |
305 | case 'T':\r | |
306 | pt = _fmt("%H:%M:%S", t, pt, ptlim, warnp);\r | |
307 | continue;\r | |
308 | case 't':\r | |
309 | pt = _add("\t", pt, ptlim);\r | |
310 | continue;\r | |
311 | case 'U':\r | |
312 | pt = _conv((t->tm_yday + DAYSPERWEEK -\r | |
313 | t->tm_wday) / DAYSPERWEEK,\r | |
314 | "%02d", pt, ptlim);\r | |
315 | continue;\r | |
316 | case 'u':\r | |
317 | /*\r | |
318 | ** From Arnold Robbins' strftime version 3.0:\r | |
319 | ** "ISO 8601: Weekday as a decimal number\r | |
320 | ** [1 (Monday) - 7]"\r | |
321 | ** (ado, 1993-05-24)\r | |
322 | */\r | |
323 | pt = _conv((t->tm_wday == 0) ?\r | |
324 | DAYSPERWEEK : t->tm_wday,\r | |
325 | "%d", pt, ptlim);\r | |
326 | continue;\r | |
327 | case 'V': /* ISO 8601 week number */\r | |
328 | case 'G': /* ISO 8601 year (four digits) */\r | |
329 | case 'g': /* ISO 8601 year (two digits) */\r | |
330 | /*\r | |
331 | ** From Arnold Robbins' strftime version 3.0: "the week number of the\r | |
332 | ** year (the first Monday as the first day of week 1) as a decimal number\r | |
333 | ** (01-53)."\r | |
334 | ** (ado, 1993-05-24)\r | |
335 | **\r | |
336 | ** From "http://www.ft.uni-erlangen.de/~mskuhn/iso-time.html" by Markus Kuhn:\r | |
337 | ** "Week 01 of a year is per definition the first week which has the\r | |
338 | ** Thursday in this year, which is equivalent to the week which contains\r | |
339 | ** the fourth day of January. In other words, the first week of a new year\r | |
340 | ** is the week which has the majority of its days in the new year. Week 01\r | |
341 | ** might also contain days from the previous year and the week before week\r | |
342 | ** 01 of a year is the last week (52 or 53) of the previous year even if\r | |
343 | ** it contains days from the new year. A week starts with Monday (day 1)\r | |
344 | ** and ends with Sunday (day 7). For example, the first week of the year\r | |
345 | ** 1997 lasts from 1996-12-30 to 1997-01-05..."\r | |
346 | ** (ado, 1996-01-02)\r | |
347 | */\r | |
348 | {\r | |
349 | int year;\r | |
350 | int yday;\r | |
351 | int wday;\r | |
352 | int w;\r | |
353 | \r | |
354 | year = t->tm_year + TM_YEAR_BASE;\r | |
355 | yday = t->tm_yday;\r | |
356 | wday = t->tm_wday;\r | |
357 | for ( ; ; ) {\r | |
358 | int len;\r | |
359 | int bot;\r | |
360 | int top;\r | |
361 | \r | |
362 | len = isleap(year) ?\r | |
363 | DAYSPERLYEAR :\r | |
364 | DAYSPERNYEAR;\r | |
365 | /*\r | |
366 | ** What yday (-3 ... 3) does\r | |
367 | ** the ISO year begin on?\r | |
368 | */\r | |
369 | bot = ((yday + 11 - wday) %\r | |
370 | DAYSPERWEEK) - 3;\r | |
371 | /*\r | |
372 | ** What yday does the NEXT\r | |
373 | ** ISO year begin on?\r | |
374 | */\r | |
375 | top = bot -\r | |
376 | (len % DAYSPERWEEK);\r | |
377 | if (top < -3)\r | |
378 | top += DAYSPERWEEK;\r | |
379 | top += len;\r | |
380 | if (yday >= top) {\r | |
381 | ++year;\r | |
382 | w = 1;\r | |
383 | break;\r | |
384 | }\r | |
385 | if (yday >= bot) {\r | |
386 | w = 1 + ((yday - bot) /\r | |
387 | DAYSPERWEEK);\r | |
388 | break;\r | |
389 | }\r | |
390 | --year;\r | |
391 | yday += isleap(year) ?\r | |
392 | DAYSPERLYEAR :\r | |
393 | DAYSPERNYEAR;\r | |
394 | }\r | |
395 | #ifdef XPG4_1994_04_09\r | |
396 | if ((w == 52\r | |
397 | && t->tm_mon == TM_JANUARY)\r | |
398 | || (w == 1\r | |
399 | && t->tm_mon == TM_DECEMBER))\r | |
400 | w = 53;\r | |
401 | #endif /* defined XPG4_1994_04_09 */\r | |
402 | if (*format == 'V')\r | |
403 | pt = _conv(w, "%02d",\r | |
404 | pt, ptlim);\r | |
405 | else if (*format == 'g') {\r | |
406 | *warnp = IN_ALL;\r | |
407 | pt = _conv(year % 100, "%02d",\r | |
408 | pt, ptlim);\r | |
409 | } else pt = _conv(year, "%04d",\r | |
410 | pt, ptlim);\r | |
411 | }\r | |
412 | continue;\r | |
413 | case 'v':\r | |
414 | /*\r | |
415 | ** From Arnold Robbins' strftime version 3.0:\r | |
416 | ** "date as dd-bbb-YYYY"\r | |
417 | ** (ado, 1993-05-24)\r | |
418 | */\r | |
419 | pt = _fmt("%e-%b-%Y", t, pt, ptlim, warnp);\r | |
420 | continue;\r | |
421 | case 'W':\r | |
422 | pt = _conv((t->tm_yday + DAYSPERWEEK -\r | |
423 | (t->tm_wday ?\r | |
424 | (t->tm_wday - 1) :\r | |
425 | (DAYSPERWEEK - 1))) / DAYSPERWEEK,\r | |
426 | "%02d", pt, ptlim);\r | |
427 | continue;\r | |
428 | case 'w':\r | |
429 | pt = _conv(t->tm_wday, "%d", pt, ptlim);\r | |
430 | continue;\r | |
431 | case 'X':\r | |
432 | pt = _fmt(Locale->t_fmt, t, pt, ptlim, warnp);\r | |
433 | continue;\r | |
434 | case 'x':\r | |
435 | {\r | |
436 | int warn2 = IN_SOME;\r | |
437 | \r | |
438 | pt = _fmt(Locale->d_fmt, t, pt, ptlim, &warn2);\r | |
439 | if (warn2 == IN_ALL)\r | |
440 | warn2 = IN_THIS;\r | |
441 | if (warn2 > *warnp)\r | |
442 | *warnp = warn2;\r | |
443 | }\r | |
444 | continue;\r | |
445 | case 'y':\r | |
446 | *warnp = IN_ALL;\r | |
447 | pt = _conv((t->tm_year + TM_YEAR_BASE) % 100,\r | |
448 | "%02d", pt, ptlim);\r | |
449 | continue;\r | |
450 | case 'Y':\r | |
451 | pt = _conv(t->tm_year + TM_YEAR_BASE, "%04d",\r | |
452 | pt, ptlim);\r | |
453 | continue;\r | |
454 | case 'Z':\r | |
455 | #ifdef TM_ZONE\r | |
456 | if (t->TM_ZONE != NULL)\r | |
457 | pt = _add(t->TM_ZONE, pt, ptlim);\r | |
458 | else\r | |
459 | #endif /* defined TM_ZONE */\r | |
460 | if (t->tm_isdst >= 0)\r | |
461 | pt = _add(tzname[t->tm_isdst != 0],\r | |
462 | pt, ptlim);\r | |
463 | /*\r | |
464 | ** C99 says that %Z must be replaced by the\r | |
465 | ** empty string if the time zone is not\r | |
466 | ** determinable.\r | |
467 | */\r | |
468 | continue;\r | |
469 | case 'z':\r | |
470 | {\r | |
471 | int diff;\r | |
472 | char const * sign;\r | |
473 | \r | |
474 | if (t->tm_isdst < 0)\r | |
475 | continue;\r | |
476 | #ifdef TM_GMTOFF\r | |
477 | diff = (int)t->TM_GMTOFF;\r | |
478 | #else /* !defined TM_GMTOFF */\r | |
479 | /*\r | |
480 | ** C99 says that the UTC offset must\r | |
481 | ** be computed by looking only at\r | |
482 | ** tm_isdst. This requirement is\r | |
483 | ** incorrect, since it means the code\r | |
484 | ** must rely on magic (in this case\r | |
485 | ** altzone and timezone), and the\r | |
486 | ** magic might not have the correct\r | |
487 | ** offset. Doing things correctly is\r | |
488 | ** tricky and requires disobeying C99;\r | |
489 | ** see GNU C strftime for details.\r | |
490 | ** For now, punt and conform to the\r | |
491 | ** standard, even though it's incorrect.\r | |
492 | **\r | |
493 | ** C99 says that %z must be replaced by the\r | |
494 | ** empty string if the time zone is not\r | |
495 | ** determinable, so output nothing if the\r | |
496 | ** appropriate variables are not available.\r | |
497 | */\r | |
498 | #ifndef STD_INSPIRED\r | |
499 | if (t->tm_isdst == 0)\r | |
500 | #ifdef USG_COMPAT\r | |
501 | diff = -timezone;\r | |
502 | #else /* !defined USG_COMPAT */\r | |
503 | continue;\r | |
504 | #endif /* !defined USG_COMPAT */\r | |
505 | else\r | |
506 | #ifdef ALTZONE\r | |
507 | diff = -altzone;\r | |
508 | #else /* !defined ALTZONE */\r | |
509 | continue;\r | |
510 | #endif /* !defined ALTZONE */\r | |
511 | #else /* defined STD_INSPIRED */\r | |
512 | {\r | |
513 | struct tm tmp;\r | |
514 | time_t lct, gct;\r | |
515 | \r | |
516 | /*\r | |
517 | ** Get calendar time from t\r | |
518 | ** being treated as local.\r | |
519 | */\r | |
520 | tmp = *t; /* mktime discards const */\r | |
521 | lct = mktime(&tmp);\r | |
522 | \r | |
523 | if (lct == (time_t)-1)\r | |
524 | continue;\r | |
525 | \r | |
526 | /*\r | |
527 | ** Get calendar time from t\r | |
528 | ** being treated as GMT.\r | |
529 | **/\r | |
530 | tmp = *t; /* mktime discards const */\r | |
531 | gct = timegm(&tmp);\r | |
532 | \r | |
533 | if (gct == (time_t)-1)\r | |
534 | continue;\r | |
535 | \r | |
536 | /* LINTED difference will fit int */\r | |
537 | diff = (intmax_t)gct - (intmax_t)lct;\r | |
538 | }\r | |
539 | #endif /* defined STD_INSPIRED */\r | |
540 | #endif /* !defined TM_GMTOFF */\r | |
541 | if (diff < 0) {\r | |
542 | sign = "-";\r | |
543 | diff = -diff;\r | |
544 | } else sign = "+";\r | |
545 | pt = _add(sign, pt, ptlim);\r | |
546 | diff /= 60;\r | |
547 | pt = _conv((diff/60)*100 + diff%60,\r | |
548 | "%04d", pt, ptlim);\r | |
549 | }\r | |
550 | continue;\r | |
551 | #if 0\r | |
552 | case '+':\r | |
553 | pt = _fmt(Locale->date_fmt, t, pt, ptlim,\r | |
554 | warnp);\r | |
555 | continue;\r | |
556 | #endif\r | |
557 | case '%':\r | |
558 | /*\r | |
559 | ** X311J/88-090 (4.12.3.5): if conversion char is\r | |
560 | ** undefined, behavior is undefined. Print out the\r | |
561 | ** character itself as printf(3) also does.\r | |
562 | */\r | |
563 | default:\r | |
564 | break;\r | |
565 | }\r | |
566 | }\r | |
567 | if (pt == ptlim)\r | |
568 | break;\r | |
569 | *pt++ = *format;\r | |
570 | }\r | |
571 | return pt;\r | |
572 | }\r | |
573 | \r | |
574 | static char *\r | |
2aa62f2b | 575 | _conv(\r |
576 | const int n,\r | |
577 | const char * const format,\r | |
578 | char * const pt,\r | |
579 | const char * const ptlim\r | |
580 | )\r | |
581 | {\r | |
582 | char buf[INT_STRLEN_MAXIMUM(int) + 1];\r | |
583 | \r | |
584 | (void) sprintf(buf, format, n);\r | |
585 | return _add(buf, pt, ptlim);\r | |
586 | }\r | |
587 | \r | |
588 | static char *\r | |
2aa62f2b | 589 | _add(\r |
590 | const char * str,\r | |
591 | char * pt,\r | |
592 | const char * const ptlim\r | |
593 | )\r | |
594 | {\r | |
595 | while (pt < ptlim && (*pt = *str++) != '\0')\r | |
596 | ++pt;\r | |
597 | return pt;\r | |
598 | }\r |