nexmon – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 /*
2 Convert a string representation of time to a time value.
3 Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
4 This file is part of the GNU C Library.
5 Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
6  
7 The GNU C Library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Library General Public License as
9 published by the Free Software Foundation; either version 2 of the
10 License, or (at your option) any later version.
11  
12 The GNU C Library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Library General Public License for more details.
16  
17 You should have received a copy of the GNU Library General Public
18 License along with the GNU C Library; see the file COPYING.LIB. If not,
19 write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301 USA. */
21  
22 /* XXX This version of the implementation is not really complete.
23 Some of the fields cannot add information alone. But if seeing
24 some of them in the same format (such as year, week and weekday)
25 this is enough information for determining the date. */
26  
27 #include "config.h"
28  
29 #include <ctype.h>
30 #include <string.h>
31 #include <glib.h>
32  
33 #ifdef _LIBC
34 # include "../locale/localeinfo.h"
35 #endif
36  
37 #include "strptime.h"
38  
39 #ifndef __P
40 # if defined (__GNUC__) || (defined (__STDC__) && __STDC__)
41 # define __P(args) args
42 # else
43 # define __P(args) ()
44 # endif /* GCC. */
45 #endif /* Not __P. */
46  
47 #if ! HAVE_LOCALTIME_R && ! defined localtime_r
48 # ifdef _LIBC
49 # define localtime_r __localtime_r
50 # else
51 /* Approximate localtime_r as best we can in its absence. */
52 # define localtime_r my_localtime_r
53 static struct tm *localtime_r __P ((const time_t *, struct tm *));
54 static struct tm *
55 localtime_r (t, tp)
56 const time_t *t;
57 struct tm *tp;
58 {
59 struct tm *l = localtime (t);
60 if (! l)
61 return 0;
62 *tp = *l;
63 return tp;
64 }
65 # endif /* ! _LIBC */
66 #endif /* ! HAVE_LOCALTIME_R && ! defined (localtime_r) */
67  
68  
69 #define match_char(ch1, ch2) if (ch1 != ch2) return NULL
70 #if defined __GNUC__ && __GNUC__ >= 2
71 # define match_string(cs1, s2) \
72 ({ size_t len = strlen (cs1); \
73 int result = g_ascii_strncasecmp ((cs1), (s2), len) == 0; \
74 if (result) (s2) += len; \
75 result; })
76 #else
77 /* Oh come on. Get a reasonable compiler. */
78 # define match_string(cs1, s2) \
79 (g_ascii_strncasecmp ((cs1), (s2), strlen (cs1)) ? 0 : ((s2) += strlen (cs1), 1))
80 #endif
81 /* We intentionally do not use isdigit() for testing because this will
82 lead to problems with the wide character version. */
83 #define get_number(from, to, n) \
84 do { \
85 int __n = n; \
86 val = 0; \
87 while (*rp == ' ') \
88 ++rp; \
89 if (*rp < '0' || *rp > '9') \
90 return NULL; \
91 do { \
92 val *= 10; \
93 val += *rp++ - '0'; \
94 } while (--__n > 0 && val * 10 <= to && *rp >= '0' && *rp <= '9'); \
95 if (val < from || val > to) \
96 return NULL; \
97 } while (0)
98 #ifdef _NL_CURRENT
99 # define get_alt_number(from, to, n) \
100 ({ \
101 __label__ do_normal; \
102 if (*decided != raw) \
103 { \
104 const char *alts = _NL_CURRENT (LC_TIME, ALT_DIGITS); \
105 int __n = n; \
106 int any = 0; \
107 while (*rp == ' ') \
108 ++rp; \
109 val = 0; \
110 do { \
111 val *= 10; \
112 while (*alts != '\0') \
113 { \
114 size_t len = strlen (alts); \
115 if (g_ascii_strncasecmp (alts, rp, len) == 0) \
116 break; \
117 alts += len + 1; \
118 ++val; \
119 } \
120 if (*alts == '\0') \
121 { \
122 if (*decided == not && ! any) \
123 goto do_normal; \
124 /* If we haven't read anything it's an error. */ \
125 if (! any) \
126 return NULL; \
127 /* Correct the premature multiplication. */ \
128 val /= 10; \
129 break; \
130 } \
131 else \
132 *decided = loc; \
133 } while (--__n > 0 && val * 10 <= to); \
134 if (val < from || val > to) \
135 return NULL; \
136 } \
137 else \
138 { \
139 do_normal: \
140 get_number (from, to, n); \
141 } \
142 0; \
143 })
144 #else
145 # define get_alt_number(from, to, n) \
146 /* We don't have the alternate representation. */ \
147 get_number(from, to, n)
148 #endif
149 #define recursive(new_fmt) \
150 (*(new_fmt) != '\0' \
151 && (rp = strptime_internal (rp, (new_fmt), tm, decided, era_cnt)) != NULL)
152  
153  
154 #ifdef _LIBC
155 /* This is defined in locale/C-time.c in the GNU libc. */
156 extern const struct locale_data _nl_C_LC_TIME;
157 extern const unsigned short int __mon_yday[2][13];
158  
159 # define weekday_name (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (DAY_1)].string)
160 # define ab_weekday_name \
161 (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (ABDAY_1)].string)
162 # define month_name (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (MON_1)].string)
163 # define ab_month_name (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (ABMON_1)].string)
164 # define HERE_D_T_FMT (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (D_T_FMT)].string)
165 # define HERE_D_FMT (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (D_FMT)].string)
166 # define HERE_AM_STR (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (AM_STR)].string)
167 # define HERE_PM_STR (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (PM_STR)].string)
168 # define HERE_T_FMT_AMPM \
169 (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (T_FMT_AMPM)].string)
170 # define HERE_T_FMT (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (T_FMT)].string)
171  
172 # define strncasecmp(s1, s2, n) __strncasecmp (s1, s2, n)
173 #else
174 static char const weekday_name[][10] =
175 {
176 "Sunday", "Monday", "Tuesday", "Wednesday",
177 "Thursday", "Friday", "Saturday"
178 };
179 static char const ab_weekday_name[][4] =
180 {
181 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
182 };
183 static char const month_name[][10] =
184 {
185 "January", "February", "March", "April", "May", "June",
186 "July", "August", "September", "October", "November", "December"
187 };
188 static char const ab_month_name[][4] =
189 {
190 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
191 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
192 };
193 # define HERE_D_T_FMT "%a %b %e %H:%M:%S %Y"
194 # define HERE_D_FMT "%m/%d/%y"
195 # define HERE_AM_STR "AM"
196 # define HERE_PM_STR "PM"
197 # define HERE_T_FMT_AMPM "%I:%M:%S %p"
198 # define HERE_T_FMT "%H:%M:%S"
199  
200 const unsigned short int __mon_yday[2][13] =
201 {
202 /* Normal years. */
203 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
204 /* Leap years. */
205 { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
206 };
207 #endif
208  
209 /* Status of lookup: do we use the locale data or the raw data? */
210 enum locale_status { not, loc, raw };
211  
212  
213 #ifndef __isleap
214 /* Nonzero if YEAR is a leap year (every 4 years,
215 except every 100th isn't, and every 400th is). */
216 # define __isleap(year) \
217 ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
218 #endif
219  
220 /* Compute the day of the week. */
221 static void
222 day_of_the_week (struct tm *tm)
223 {
224 /* We know that January 1st 1970 was a Thursday (= 4). Compute the
225 the difference between this data in the one on TM and so determine
226 the weekday. */
227 int corr_year = 1900 + tm->tm_year - (tm->tm_mon < 2);
228 int wday = (-473
229 + (365 * (tm->tm_year - 70))
230 + (corr_year / 4)
231 - ((corr_year / 4) / 25) + ((corr_year / 4) % 25 < 0)
232 + (((corr_year / 4) / 25) / 4)
233 + __mon_yday[0][tm->tm_mon]
234 + tm->tm_mday - 1);
235 tm->tm_wday = ((wday % 7) + 7) % 7;
236 }
237  
238 /* Compute the day of the year. */
239 static void
240 day_of_the_year (struct tm *tm)
241 {
242 tm->tm_yday = (__mon_yday[__isleap (1900 + tm->tm_year)][tm->tm_mon]
243 + (tm->tm_mday - 1));
244 }
245  
246 static char *
247 #ifdef _LIBC
248 internal_function
249 #endif
250 strptime_internal __P ((const char *rp, const char *fmt, struct tm *tm,
251 enum locale_status *decided, int era_cnt));
252  
253 static char *
254 #ifdef _LIBC
255 internal_function
256 #endif
257 strptime_internal (rp, fmt, tm, decided, era_cnt)
258 const char *rp;
259 const char *fmt;
260 struct tm *tm;
261 enum locale_status *decided;
262 int era_cnt;
263 {
264 const char *rp_backup;
265 int cnt;
266 int val;
267 int have_I, is_pm;
268 int century, want_century;
269 int want_era;
270 int have_wday, want_xday;
271 int have_yday;
272 int have_mon, have_mday;
273 #ifdef _NL_CURRENT
274 size_t num_eras;
275 #endif
276 struct era_entry *era;
277  
278 have_I = is_pm = 0;
279 century = -1;
280 want_century = 0;
281 want_era = 0;
282 era = NULL;
283  
284 have_wday = want_xday = have_yday = have_mon = have_mday = 0;
285  
286 while (*fmt != '\0')
287 {
288 /* A white space in the format string matches 0 more or white
289 space in the input string. */
290 if (isspace (*fmt))
291 {
292 while (isspace (*rp))
293 ++rp;
294 ++fmt;
295 continue;
296 }
297  
298 /* Any character but `%' must be matched by the same character
299 in the iput string. */
300 if (*fmt != '%')
301 {
302 match_char (*fmt++, *rp++);
303 continue;
304 }
305  
306 ++fmt;
307 #ifndef _NL_CURRENT
308 /* We need this for handling the `E' modifier. */
309 start_over:
310 #endif
311  
312 /* Make back up of current processing pointer. */
313 rp_backup = rp;
314  
315 switch (*fmt++)
316 {
317 case '%':
318 /* Match the `%' character itself. */
319 match_char ('%', *rp++);
320 break;
321 case 'a':
322 case 'A':
323 /* Match day of week. */
324 for (cnt = 0; cnt < 7; ++cnt)
325 {
326 #ifdef _NL_CURRENT
327 if (*decided !=raw)
328 {
329 if (match_string (_NL_CURRENT (LC_TIME, DAY_1 + cnt), rp))
330 {
331 if (*decided == not
332 && strcmp (_NL_CURRENT (LC_TIME, DAY_1 + cnt),
333 weekday_name[cnt]))
334 *decided = loc;
335 break;
336 }
337 if (match_string (_NL_CURRENT (LC_TIME, ABDAY_1 + cnt), rp))
338 {
339 if (*decided == not
340 && strcmp (_NL_CURRENT (LC_TIME, ABDAY_1 + cnt),
341 ab_weekday_name[cnt]))
342 *decided = loc;
343 break;
344 }
345 }
346 #endif
347 if (*decided != loc
348 && (match_string (weekday_name[cnt], rp)
349 || match_string (ab_weekday_name[cnt], rp)))
350 {
351 *decided = raw;
352 break;
353 }
354 }
355 if (cnt == 7)
356 /* Does not match a weekday name. */
357 return NULL;
358 tm->tm_wday = cnt;
359 have_wday = 1;
360 break;
361 case 'b':
362 case 'B':
363 case 'h':
364 /* Match month name. */
365 for (cnt = 0; cnt < 12; ++cnt)
366 {
367 #ifdef _NL_CURRENT
368 if (*decided !=raw)
369 {
370 if (match_string (_NL_CURRENT (LC_TIME, MON_1 + cnt), rp))
371 {
372 if (*decided == not
373 && strcmp (_NL_CURRENT (LC_TIME, MON_1 + cnt),
374 month_name[cnt]))
375 *decided = loc;
376 break;
377 }
378 if (match_string (_NL_CURRENT (LC_TIME, ABMON_1 + cnt), rp))
379 {
380 if (*decided == not
381 && strcmp (_NL_CURRENT (LC_TIME, ABMON_1 + cnt),
382 ab_month_name[cnt]))
383 *decided = loc;
384 break;
385 }
386 }
387 #endif
388 if (match_string (month_name[cnt], rp)
389 || match_string (ab_month_name[cnt], rp))
390 {
391 *decided = raw;
392 break;
393 }
394 }
395 if (cnt == 12)
396 /* Does not match a month name. */
397 return NULL;
398 tm->tm_mon = cnt;
399 want_xday = 1;
400 break;
401 case 'c':
402 /* Match locale's date and time format. */
403 #ifdef _NL_CURRENT
404 if (*decided != raw)
405 {
406 if (!recursive (_NL_CURRENT (LC_TIME, D_T_FMT)))
407 {
408 if (*decided == loc)
409 return NULL;
410 else
411 rp = rp_backup;
412 }
413 else
414 {
415 if (*decided == not &&
416 strcmp (_NL_CURRENT (LC_TIME, D_T_FMT), HERE_D_T_FMT))
417 *decided = loc;
418 want_xday = 1;
419 break;
420 }
421 *decided = raw;
422 }
423 #endif
424 if (!recursive (HERE_D_T_FMT))
425 return NULL;
426 want_xday = 1;
427 break;
428 case 'C':
429 /* Match century number. */
430 #ifdef _NL_CURRENT
431 match_century:
432 #endif
433 get_number (0, 99, 2);
434 century = val;
435 want_xday = 1;
436 break;
437 case 'd':
438 case 'e':
439 /* Match day of month. */
440 get_number (1, 31, 2);
441 tm->tm_mday = val;
442 have_mday = 1;
443 want_xday = 1;
444 break;
445 case 'F':
446 if (!recursive ("%Y-%m-%d"))
447 return NULL;
448 want_xday = 1;
449 break;
450 case 'x':
451 #ifdef _NL_CURRENT
452 if (*decided != raw)
453 {
454 if (!recursive (_NL_CURRENT (LC_TIME, D_FMT)))
455 {
456 if (*decided == loc)
457 return NULL;
458 else
459 rp = rp_backup;
460 }
461 else
462 {
463 if (*decided == not
464 && strcmp (_NL_CURRENT (LC_TIME, D_FMT), HERE_D_FMT))
465 *decided = loc;
466 want_xday = 1;
467 break;
468 }
469 *decided = raw;
470 }
471 #endif
472 /* Fall through. */
473 case 'D':
474 /* Match standard day format. */
475 if (!recursive (HERE_D_FMT))
476 return NULL;
477 want_xday = 1;
478 break;
479 case 'k':
480 case 'H':
481 /* Match hour in 24-hour clock. */
482 get_number (0, 23, 2);
483 tm->tm_hour = val;
484 have_I = 0;
485 break;
486 case 'I':
487 /* Match hour in 12-hour clock. */
488 get_number (1, 12, 2);
489 tm->tm_hour = val % 12;
490 have_I = 1;
491 break;
492 case 'j':
493 /* Match day number of year. */
494 get_number (1, 366, 3);
495 tm->tm_yday = val - 1;
496 have_yday = 1;
497 break;
498 case 'm':
499 /* Match number of month. */
500 get_number (1, 12, 2);
501 tm->tm_mon = val - 1;
502 have_mon = 1;
503 want_xday = 1;
504 break;
505 case 'M':
506 /* Match minute. */
507 get_number (0, 59, 2);
508 tm->tm_min = val;
509 break;
510 case 'n':
511 case 't':
512 /* Match any white space. */
513 while (isspace (*rp))
514 ++rp;
515 break;
516 case 'p':
517 /* Match locale's equivalent of AM/PM. */
518 #ifdef _NL_CURRENT
519 if (*decided != raw)
520 {
521 if (match_string (_NL_CURRENT (LC_TIME, AM_STR), rp))
522 {
523 if (strcmp (_NL_CURRENT (LC_TIME, AM_STR), HERE_AM_STR))
524 *decided = loc;
525 break;
526 }
527 if (match_string (_NL_CURRENT (LC_TIME, PM_STR), rp))
528 {
529 if (strcmp (_NL_CURRENT (LC_TIME, PM_STR), HERE_PM_STR))
530 *decided = loc;
531 is_pm = 1;
532 break;
533 }
534 *decided = raw;
535 }
536 #endif
537 if (!match_string (HERE_AM_STR, rp)) {
538 if (match_string (HERE_PM_STR, rp))
539 is_pm = 1;
540 else
541 return NULL;
542 }
543 break;
544 case 'r':
545 #ifdef _NL_CURRENT
546 if (*decided != raw)
547 {
548 if (!recursive (_NL_CURRENT (LC_TIME, T_FMT_AMPM)))
549 {
550 if (*decided == loc)
551 return NULL;
552 else
553 rp = rp_backup;
554 }
555 else
556 {
557 if (*decided == not &&
558 strcmp (_NL_CURRENT (LC_TIME, T_FMT_AMPM),
559 HERE_T_FMT_AMPM))
560 *decided = loc;
561 break;
562 }
563 *decided = raw;
564 }
565 #endif
566 if (!recursive (HERE_T_FMT_AMPM))
567 return NULL;
568 break;
569 case 'R':
570 if (!recursive ("%H:%M"))
571 return NULL;
572 break;
573 case 's':
574 {
575 /* The number of seconds may be very high so we cannot use
576 the `get_number' macro. Instead read the number
577 character for character and construct the result while
578 doing this. */
579 time_t secs = 0;
580 if (*rp < '0' || *rp > '9')
581 /* We need at least one digit. */
582 return NULL;
583  
584 do
585 {
586 secs *= 10;
587 secs += *rp++ - '0';
588 }
589 while (*rp >= '0' && *rp <= '9');
590  
591 if (localtime_r (&secs, tm) == NULL)
592 /* Error in function. */
593 return NULL;
594 }
595 break;
596 case 'S':
597 get_number (0, 61, 2);
598 tm->tm_sec = val;
599 break;
600 case 'X':
601 #ifdef _NL_CURRENT
602 if (*decided != raw)
603 {
604 if (!recursive (_NL_CURRENT (LC_TIME, T_FMT)))
605 {
606 if (*decided == loc)
607 return NULL;
608 else
609 rp = rp_backup;
610 }
611 else
612 {
613 if (strcmp (_NL_CURRENT (LC_TIME, T_FMT), HERE_T_FMT))
614 *decided = loc;
615 break;
616 }
617 *decided = raw;
618 }
619 #endif
620 /* Fall through. */
621 case 'T':
622 if (!recursive (HERE_T_FMT))
623 return NULL;
624 break;
625 case 'u':
626 get_number (1, 7, 1);
627 tm->tm_wday = val % 7;
628 have_wday = 1;
629 break;
630 case 'g':
631 get_number (0, 99, 2);
632 /* XXX This cannot determine any field in TM. */
633 break;
634 case 'G':
635 if (*rp < '0' || *rp > '9')
636 return NULL;
637 /* XXX Ignore the number since we would need some more
638 information to compute a real date. */
639 do
640 ++rp;
641 while (*rp >= '0' && *rp <= '9');
642 break;
643 case 'U':
644 case 'V':
645 case 'W':
646 get_number (0, 53, 2);
647 /* XXX This cannot determine any field in TM without some
648 information. */
649 break;
650 case 'w':
651 /* Match number of weekday. */
652 get_number (0, 6, 1);
653 tm->tm_wday = val;
654 have_wday = 1;
655 break;
656 case 'y':
657 #ifdef _NL_CURRENT
658 match_year_in_century:
659 #endif
660 /* Match year within century. */
661 get_number (0, 99, 2);
662 /* The "Year 2000: The Millennium Rollover" paper suggests that
663 values in the range 69-99 refer to the twentieth century. */
664 tm->tm_year = val >= 69 ? val : val + 100;
665 /* Indicate that we want to use the century, if specified. */
666 want_century = 1;
667 want_xday = 1;
668 break;
669 case 'Y':
670 /* Match year including century number. */
671 get_number (0, 9999, 4);
672 tm->tm_year = val - 1900;
673 want_century = 0;
674 want_xday = 1;
675 break;
676 case 'Z':
677 /* XXX How to handle this? */
678 break;
679 case 'E':
680 #ifdef _NL_CURRENT
681 switch (*fmt++)
682 {
683 case 'c':
684 /* Match locale's alternate date and time format. */
685 if (*decided != raw)
686 {
687 const char *fmt = _NL_CURRENT (LC_TIME, ERA_D_T_FMT);
688  
689 if (*fmt == '\0')
690 fmt = _NL_CURRENT (LC_TIME, D_T_FMT);
691  
692 if (!recursive (fmt))
693 {
694 if (*decided == loc)
695 return NULL;
696 else
697 rp = rp_backup;
698 }
699 else
700 {
701 if (strcmp (fmt, HERE_D_T_FMT))
702 *decided = loc;
703 want_xday = 1;
704 break;
705 }
706 *decided = raw;
707 }
708 /* The C locale has no era information, so use the
709 normal representation. */
710 if (!recursive (HERE_D_T_FMT))
711 return NULL;
712 want_xday = 1;
713 break;
714 case 'C':
715 if (*decided != raw)
716 {
717 if (era_cnt >= 0)
718 {
719 era = _nl_select_era_entry (era_cnt);
720 if (match_string (era->era_name, rp))
721 {
722 *decided = loc;
723 break;
724 }
725 else
726 return NULL;
727 }
728 else
729 {
730 num_eras = _NL_CURRENT_WORD (LC_TIME,
731 _NL_TIME_ERA_NUM_ENTRIES);
732 for (era_cnt = 0; era_cnt < (int) num_eras;
733 ++era_cnt, rp = rp_backup)
734 {
735 era = _nl_select_era_entry (era_cnt);
736 if (match_string (era->era_name, rp))
737 {
738 *decided = loc;
739 break;
740 }
741 }
742 if (era_cnt == (int) num_eras)
743 {
744 era_cnt = -1;
745 if (*decided == loc)
746 return NULL;
747 }
748 else
749 break;
750 }
751  
752 *decided = raw;
753 }
754 /* The C locale has no era information, so use the
755 normal representation. */
756 goto match_century;
757 case 'y':
758 if (*decided == raw)
759 goto match_year_in_century;
760  
761 get_number(0, 9999, 4);
762 tm->tm_year = val;
763 want_era = 1;
764 want_xday = 1;
765 break;
766 case 'Y':
767 if (*decided != raw)
768 {
769 num_eras = _NL_CURRENT_WORD (LC_TIME,
770 _NL_TIME_ERA_NUM_ENTRIES);
771 for (era_cnt = 0; era_cnt < (int) num_eras;
772 ++era_cnt, rp = rp_backup)
773 {
774 era = _nl_select_era_entry (era_cnt);
775 if (recursive (era->era_format))
776 break;
777 }
778 if (era_cnt == (int) num_eras)
779 {
780 era_cnt = -1;
781 if (*decided == loc)
782 return NULL;
783 else
784 rp = rp_backup;
785 }
786 else
787 {
788 *decided = loc;
789 era_cnt = -1;
790 break;
791 }
792  
793 *decided = raw;
794 }
795 get_number (0, 9999, 4);
796 tm->tm_year = val - 1900;
797 want_century = 0;
798 want_xday = 1;
799 break;
800 case 'x':
801 if (*decided != raw)
802 {
803 const char *fmt = _NL_CURRENT (LC_TIME, ERA_D_FMT);
804  
805 if (*fmt == '\0')
806 fmt = _NL_CURRENT (LC_TIME, D_FMT);
807  
808 if (!recursive (fmt))
809 {
810 if (*decided == loc)
811 return NULL;
812 else
813 rp = rp_backup;
814 }
815 else
816 {
817 if (strcmp (fmt, HERE_D_FMT))
818 *decided = loc;
819 break;
820 }
821 *decided = raw;
822 }
823 if (!recursive (HERE_D_FMT))
824 return NULL;
825 break;
826 case 'X':
827 if (*decided != raw)
828 {
829 const char *fmt = _NL_CURRENT (LC_TIME, ERA_T_FMT);
830  
831 if (*fmt == '\0')
832 fmt = _NL_CURRENT (LC_TIME, T_FMT);
833  
834 if (!recursive (fmt))
835 {
836 if (*decided == loc)
837 return NULL;
838 else
839 rp = rp_backup;
840 }
841 else
842 {
843 if (strcmp (fmt, HERE_T_FMT))
844 *decided = loc;
845 break;
846 }
847 *decided = raw;
848 }
849 if (!recursive (HERE_T_FMT))
850 return NULL;
851 break;
852 default:
853 return NULL;
854 }
855 break;
856 #else
857 /* We have no information about the era format. Just use
858 the normal format. */
859 if (*fmt != 'c' && *fmt != 'C' && *fmt != 'y' && *fmt != 'Y'
860 && *fmt != 'x' && *fmt != 'X')
861 /* This is an illegal format. */
862 return NULL;
863  
864 goto start_over;
865 #endif
866 case 'O':
867 switch (*fmt++)
868 {
869 case 'd':
870 case 'e':
871 /* Match day of month using alternate numeric symbols. */
872 get_alt_number (1, 31, 2);
873 tm->tm_mday = val;
874 have_mday = 1;
875 want_xday = 1;
876 break;
877 case 'H':
878 /* Match hour in 24-hour clock using alternate numeric
879 symbols. */
880 get_alt_number (0, 23, 2);
881 tm->tm_hour = val;
882 have_I = 0;
883 break;
884 case 'I':
885 /* Match hour in 12-hour clock using alternate numeric
886 symbols. */
887 get_alt_number (1, 12, 2);
888 tm->tm_hour = val - 1;
889 have_I = 1;
890 break;
891 case 'm':
892 /* Match month using alternate numeric symbols. */
893 get_alt_number (1, 12, 2);
894 tm->tm_mon = val - 1;
895 have_mon = 1;
896 want_xday = 1;
897 break;
898 case 'M':
899 /* Match minutes using alternate numeric symbols. */
900 get_alt_number (0, 59, 2);
901 tm->tm_min = val;
902 break;
903 case 'S':
904 /* Match seconds using alternate numeric symbols. */
905 get_alt_number (0, 61, 2);
906 tm->tm_sec = val;
907 break;
908 case 'U':
909 case 'V':
910 case 'W':
911 get_alt_number (0, 53, 2);
912 /* XXX This cannot determine any field in TM without
913 further information. */
914 break;
915 case 'w':
916 /* Match number of weekday using alternate numeric symbols. */
917 get_alt_number (0, 6, 1);
918 tm->tm_wday = val;
919 have_wday = 1;
920 break;
921 case 'y':
922 /* Match year within century using alternate numeric symbols. */
923 get_alt_number (0, 99, 2);
924 tm->tm_year = val >= 69 ? val : val + 100;
925 want_xday = 1;
926 break;
927 default:
928 return NULL;
929 }
930 break;
931 default:
932 return NULL;
933 }
934 }
935  
936 if (have_I && is_pm)
937 tm->tm_hour += 12;
938  
939 if (century != -1)
940 {
941 if (want_century)
942 tm->tm_year = tm->tm_year % 100 + (century - 19) * 100;
943 else
944 /* Only the century, but not the year. Strange, but so be it. */
945 tm->tm_year = (century - 19) * 100;
946 }
947  
948 #ifdef _NL_CURRENT
949 if (era_cnt != -1)
950 {
951 era = _nl_select_era_entry(era_cnt);
952 if (want_era)
953 tm->tm_year = (era->start_date[0]
954 + ((tm->tm_year - era->offset)
955 * era->absolute_direction));
956 else
957 /* Era start year assumed. */
958 tm->tm_year = era->start_date[0];
959 }
960 else
961 #endif
962 if (want_era)
963 return NULL;
964  
965 if (want_xday && !have_wday)
966 {
967 if ( !(have_mon && have_mday) && have_yday)
968 {
969 /* We don't have tm_mon and/or tm_mday, compute them. */
970 int t_mon = 0;
971 while (__mon_yday[__isleap(1900 + tm->tm_year)][t_mon] <= tm->tm_yday)
972 t_mon++;
973 if (!have_mon)
974 tm->tm_mon = t_mon - 1;
975 if (!have_mday)
976 tm->tm_mday =
977 (tm->tm_yday
978 - __mon_yday[__isleap(1900 + tm->tm_year)][t_mon - 1] + 1);
979 }
980 day_of_the_week (tm);
981 }
982 if (want_xday && !have_yday)
983 day_of_the_year (tm);
984  
985 return (char *) rp;
986 }
987  
988  
989 char *
990 strptime (buf, format, tm)
991 const char *buf;
992 const char *format;
993 struct tm *tm;
994 {
995 enum locale_status decided;
996  
997 #ifdef _NL_CURRENT
998 decided = not;
999 #else
1000 decided = raw;
1001 #endif
1002 return strptime_internal (buf, format, tm, &decided, -1);
1003 }
1004  
1005 /*
1006 * Editor modelines - http://www.wireshark.org/tools/modelines.html
1007 *
1008 * Local Variables:
1009 * c-basic-offset: 2
1010 * tab-width: 8
1011 * indent-tabs-mode: nil
1012 * End:
1013 *
1014 * ex: set shiftwidth=2 tabstop=8 expandtab:
1015 * :indentSize=2:tabSize=8:noTabs=true:
1016 */