comparison src/protocols/msn/msn-utils.c @ 19794:b22d13f55232

[gaim-migrate @ 16684] change the code of SOAP Action,Now using a stupid way to do the soap, wish to implement it in a clean way! borrow a strptime to parse the timestamp received from MSN Server. committed by MaYuan<mayuan2006@gmail.com> committer: Ethan Blanton <elb@pidgin.im>
author Ma Yuan <mayuan2006@gmail.com>
date Thu, 10 Aug 2006 04:38:13 +0000
parents 8b4653986e8e
children a8d00b8dae40
comparison
equal deleted inserted replaced
19793:1b48fbbd0e61 19794:b22d13f55232
21 * along with this program; if not, write to the Free Software 21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 */ 23 */
24 #include "msn.h" 24 #include "msn.h"
25 #include "msn-utils.h" 25 #include "msn-utils.h"
26 #include "time.h"
26 //#include <openssl/md5.h> 27 //#include <openssl/md5.h>
27 28
28 void 29 void
29 msn_parse_format(const char *mime, char **pre_ret, char **post_ret) 30 msn_parse_format(const char *mime, char **pre_ret, char **post_ret)
30 { 31 {
360 } 361 }
361 362
362 *ret_host = host; 363 *ret_host = host;
363 *ret_port = port; 364 *ret_port = port;
364 } 365 }
365 366 /***************************************************************************
367 * MSN Time Related Funciton
368 ***************************************************************************/
369 #if 0
370 int
371 msn_convert_iso8601(const char *timestr,struct tm tm_time)
372 {
373 char temp[64];
374 struct tm ctime;
375 time_t ts;
376
377 gaim_debug_info("MaYuan","convert string is{%s}\n",timestr);
378 tzset();
379 /*copy string first*/
380 memset(temp, 0, sizeof(temp));
381 strncpy(temp, timestr, strlen(timestr));
382
383 /*convert via strptime()*/
384 memset(&ctime, 0, sizeof(struct tm));
385 strptime(temp, "%d %b %Y %T %Z", &ctime);
386 ts = mktime(&ctime) - timezone;
387 localtime_r(&ts, tm_time);
388 }
389 #endif
390
391 /***************************************************************************
392 * MSN Challenge Computing Function
393 ***************************************************************************/
366 /*check the edian of system*/ 394 /*check the edian of system*/
367 int 395 int
368 isBigEndian(void) 396 isBigEndian(void)
369 { 397 {
370 short int word = 0x0100; 398 short int word = 0x0100;
480 output[32]='\0'; 508 output[32]='\0';
481 509
482 // gaim_debug_info("MaYuan","chl output{%s}\n",output); 510 // gaim_debug_info("MaYuan","chl output{%s}\n",output);
483 } 511 }
484 512
513 #if (!defined(_XOPEN_SOURCE))||defined(_WIN32)
514
515 #ifndef __P
516 # if defined (__GNUC__) || (defined (__STDC__) && __STDC__)
517 # define __P(args) args
518 # else
519 # define __P(args) ()
520 # endif /* GCC. */
521 #endif /* Not __P. */
522
523 #if ! HAVE_LOCALTIME_R && ! defined localtime_r
524 # ifdef _LIBC
525 # define localtime_r __localtime_r
526 # else
527 /* Approximate localtime_r as best we can in its absence. */
528 # define localtime_r my_localtime_r
529 static struct tm *localtime_r __P ((const time_t *, struct tm *));
530 static struct tm *
531 localtime_r (t, tp)
532 const time_t *t;
533 struct tm *tp;
534 {
535 struct tm *l = localtime (t);
536 if (! l)
537 return 0;
538 *tp = *l;
539 return tp;
540 }
541 # endif /* ! _LIBC */
542 #endif /* ! HAVE_LOCALTIME_R && ! defined (localtime_r) */
543
544
545 #define match_char(ch1, ch2) if (ch1 != ch2) return NULL
546
547 #if defined __GNUC__ && __GNUC__ >= 2
548 # define match_string(cs1, s2) \
549 ({ size_t len = strlen (cs1); \
550 int result = strncasecmp ((cs1), (s2), len) == 0; \
551 if (result) (s2) += len; \
552 result; })
553 #else
554 /* Oh come on. Get a reasonable compiler. */
555 # define match_string(cs1, s2) \
556 (strncasecmp ((cs1), (s2), strlen (cs1)) ? 0 : ((s2) += strlen (cs1), 1))
557 #endif
558
559 /* We intentionally do not use isdigit() for testing because this will
560 lead to problems with the wide character version. */
561 #define get_number(from, to, n) \
562 do { \
563 int __n = n; \
564 val = 0; \
565 while (*rp == ' ') \
566 ++rp; \
567 if ((*rp < '0') || (*rp > '9')) \
568 return NULL; \
569 do { \
570 val *= 10; \
571 val += *rp++ - '0'; \
572 } while ((--__n > 0) && (val * 10 <= to) && (*rp >= '0') && (*rp <= '9')); \
573 if ((val < from) || (val > to)) \
574 return NULL; \
575 } while (0)
576
577 #ifdef _NL_CURRENT
578 # define get_alt_number(from, to, n) \
579 ({ \
580 __label__ do_normal; \
581 if (*decided != raw) \
582 { \
583 const char *alts = _NL_CURRENT (LC_TIME, ALT_DIGITS); \
584 int __n = n; \
585 int any = 0; \
586 while (*rp == ' ') \
587 ++rp; \
588 val = 0; \
589 do { \
590 val *= 10; \
591 while (*alts != '\0') \
592 { \
593 size_t len = strlen (alts); \
594 if (strncasecmp (alts, rp, len) == 0) \
595 break; \
596 alts += len + 1; \
597 ++val; \
598 } \
599 if (*alts == '\0') \
600 { \
601 if (*decided == not && ! any) \
602 goto do_normal; \
603 /* If we haven't read anything it's an error. */ \
604 if (! any) \
605 return NULL; \
606 /* Correct the premature multiplication. */ \
607 val /= 10; \
608 break; \
609 } \
610 else \
611 *decided = loc; \
612 } while (--__n > 0 && val * 10 <= to); \
613 if (val < from || val > to) \
614 return NULL; \
615 } \
616 else \
617 { \
618 do_normal: \
619 get_number (from, to, n); \
620 } \
621 0; \
622 })
623 #else
624 # define get_alt_number(from, to, n) \
625 /* We don't have the alternate representation. */ \
626 get_number(from, to, n)
627 #endif
628
629 #define recursive(new_fmt) \
630 (*(new_fmt) != '\0' \
631 && (rp = strptime_internal (rp, (new_fmt), tm, decided, era_cnt)) != NULL)
632
633
634 #ifdef _LIBC
635 /* This is defined in locale/C-time.c in the GNU libc. */
636 extern const struct locale_data _nl_C_LC_TIME;
637 extern const unsigned short int __mon_yday[2][13];
638
639 # define weekday_name (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (DAY_1)].string)
640 # define ab_weekday_name \
641 (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (ABDAY_1)].string)
642 # define month_name (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (MON_1)].string)
643 # define ab_month_name (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (ABMON_1)].string)
644 # define HERE_D_T_FMT (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (D_T_FMT)].string)
645 # define HERE_D_FMT (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (D_FMT)].string)
646 # define HERE_AM_STR (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (AM_STR)].string)
647 # define HERE_PM_STR (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (PM_STR)].string)
648 # define HERE_T_FMT_AMPM \
649 (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (T_FMT_AMPM)].string)
650 # define HERE_T_FMT (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (T_FMT)].string)
651
652 # define strncasecmp(s1, s2, n) __strncasecmp (s1, s2, n)
653 #else
654 static char const weekday_name[][10] =
655 {
656 "Sunday", "Monday", "Tuesday", "Wednesday",
657 "Thursday", "Friday", "Saturday"
658 };
659 static char const ab_weekday_name[][4] =
660 {
661 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
662 };
663 static char const month_name[][10] =
664 {
665 "January", "February", "March", "April", "May", "June",
666 "July", "August", "September", "October", "November", "December"
667 };
668 static char const ab_month_name[][4] =
669 {
670 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
671 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
672 };
673 # define HERE_D_T_FMT "%a %b %e %H:%M:%S %Y"
674 # define HERE_D_FMT "%m/%d/%y"
675 # define HERE_AM_STR "AM"
676 # define HERE_PM_STR "PM"
677 # define HERE_T_FMT_AMPM "%I:%M:%S %p"
678 # define HERE_T_FMT "%H:%M:%S"
679
680 const unsigned short int __mon_yday[2][13] =
681 {
682 /* Normal years. */
683 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
684 /* Leap years. */
685 { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
686 };
687 #endif
688
689 /* Status of lookup: do we use the locale data or the raw data? */
690 enum locale_status { not, loc, raw };
691
692
693 #ifndef __isleap
694 /* Nonzero if YEAR is a leap year (every 4 years,
695 except every 100th isn't, and every 400th is). */
696 # define __isleap(year) \
697 ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
698 #endif
699
700 /* Compute the day of the week. */
701 static void
702 day_of_the_week (struct tm *tm)
703 {
704 /* We know that January 1st 1970 was a Thursday (= 4). Compute the
705 the difference between this data in the one on TM and so determine
706 the weekday. */
707 int corr_year = 1900 + tm->tm_year - (tm->tm_mon < 2);
708 int wday = (-473
709 + (365 * (tm->tm_year - 70))
710 + (corr_year / 4)
711 - ((corr_year / 4) / 25) + ((corr_year / 4) % 25 < 0)
712 + (((corr_year / 4) / 25) / 4)
713 + __mon_yday[0][tm->tm_mon]
714 + tm->tm_mday - 1);
715 tm->tm_wday = ((wday % 7) + 7) % 7;
716 }
717
718 /* Compute the day of the year. */
719 static void
720 day_of_the_year (struct tm *tm)
721 {
722 tm->tm_yday = (__mon_yday[__isleap (1900 + tm->tm_year)][tm->tm_mon]
723 + (tm->tm_mday - 1));
724 }
725
726 static char *
727 #ifdef _LIBC
728 internal_function
729 #endif
730 strptime_internal __P ((const char *rp, const char *fmt, struct tm *tm,
731 enum locale_status *decided, int era_cnt));
732
733 static char *
734 #ifdef _LIBC
735 internal_function
736 #endif
737 strptime_internal (rp, fmt, tm, decided, era_cnt)
738 const char *rp;
739 const char *fmt;
740 struct tm *tm;
741 enum locale_status *decided;
742 int era_cnt;
743 {
744 const char *rp_backup;
745 int cnt;
746 size_t val;
747 int have_I, is_pm;
748 int century, want_century;
749 int want_era;
750 int have_wday, want_xday;
751 int have_yday;
752 int have_mon, have_mday;
753 #ifdef _NL_CURRENT
754 size_t num_eras;
755 #endif
756 struct era_entry *era;
757
758 have_I = is_pm = 0;
759 century = -1;
760 want_century = 0;
761 want_era = 0;
762 era = NULL;
763
764 have_wday = want_xday = have_yday = have_mon = have_mday = 0;
765
766 while (*fmt != '\0')
767 {
768 /* A white space in the format string matches 0 more or white
769 space in the input string. */
770 if (isspace (*fmt))
771 {
772 while (isspace (*rp))
773 ++rp;
774 ++fmt;
775 continue;
776 }
777
778 /* Any character but `%' must be matched by the same character
779 in the iput string. */
780 if (*fmt != '%')
781 {
782 match_char (*fmt++, *rp++);
783 continue;
784 }
785
786 ++fmt;
787 #ifndef _NL_CURRENT
788 /* We need this for handling the `E' modifier. */
789 start_over:
790 #endif
791
792 /* Make back up of current processing pointer. */
793 rp_backup = rp;
794
795 switch (*fmt++)
796 {
797 case '%':
798 /* Match the `%' character itself. */
799 match_char ('%', *rp++);
800 break;
801 case 'a':
802 case 'A':
803 /* Match day of week. */
804 for (cnt = 0; cnt < 7; ++cnt)
805 {
806 #ifdef _NL_CURRENT
807 if (*decided !=raw)
808 {
809 if (match_string (_NL_CURRENT (LC_TIME, DAY_1 + cnt), rp))
810 {
811 if (*decided == not
812 && strcmp (_NL_CURRENT (LC_TIME, DAY_1 + cnt),
813 weekday_name[cnt]))
814 *decided = loc;
815 break;
816 }
817 if (match_string (_NL_CURRENT (LC_TIME, ABDAY_1 + cnt), rp))
818 {
819 if (*decided == not
820 && strcmp (_NL_CURRENT (LC_TIME, ABDAY_1 + cnt),
821 ab_weekday_name[cnt]))
822 *decided = loc;
823 break;
824 }
825 }
826 #endif
827 if (*decided != loc
828 && (match_string (weekday_name[cnt], rp)
829 || match_string (ab_weekday_name[cnt], rp)))
830 {
831 *decided = raw;
832 break;
833 }
834 }
835 if (cnt == 7)
836 /* Does not match a weekday name. */
837 return NULL;
838 tm->tm_wday = cnt;
839 have_wday = 1;
840 break;
841 case 'b':
842 case 'B':
843 case 'h':
844 /* Match month name. */
845 for (cnt = 0; cnt < 12; ++cnt)
846 {
847 #ifdef _NL_CURRENT
848 if (*decided !=raw)
849 {
850 if (match_string (_NL_CURRENT (LC_TIME, MON_1 + cnt), rp))
851 {
852 if (*decided == not
853 && strcmp (_NL_CURRENT (LC_TIME, MON_1 + cnt),
854 month_name[cnt]))
855 *decided = loc;
856 break;
857 }
858 if (match_string (_NL_CURRENT (LC_TIME, ABMON_1 + cnt), rp))
859 {
860 if (*decided == not
861 && strcmp (_NL_CURRENT (LC_TIME, ABMON_1 + cnt),
862 ab_month_name[cnt]))
863 *decided = loc;
864 break;
865 }
866 }
867 #endif
868 if (match_string (month_name[cnt], rp)
869 || match_string (ab_month_name[cnt], rp))
870 {
871 *decided = raw;
872 break;
873 }
874 }
875 if (cnt == 12)
876 /* Does not match a month name. */
877 return NULL;
878 tm->tm_mon = cnt;
879 want_xday = 1;
880 break;
881 case 'c':
882 /* Match locale's date and time format. */
883 #ifdef _NL_CURRENT
884 if (*decided != raw)
885 {
886 if (!recursive (_NL_CURRENT (LC_TIME, D_T_FMT)))
887 {
888 if (*decided == loc)
889 return NULL;
890 else
891 rp = rp_backup;
892 }
893 else
894 {
895 if (*decided == not &&
896 strcmp (_NL_CURRENT (LC_TIME, D_T_FMT), HERE_D_T_FMT))
897 *decided = loc;
898 want_xday = 1;
899 break;
900 }
901 *decided = raw;
902 }
903 #endif
904 if (!recursive (HERE_D_T_FMT))
905 return NULL;
906 want_xday = 1;
907 break;
908 case 'C':
909 /* Match century number. */
910 #ifdef _NL_CURRENT
911 match_century:
912 #endif
913 get_number (0, 99, 2);
914 century = val;
915 want_xday = 1;
916 break;
917 case 'd':
918 case 'e':
919 /* Match day of month. */
920 get_number (1, 31, 2);
921 tm->tm_mday = val;
922 have_mday = 1;
923 want_xday = 1;
924 break;
925 case 'F':
926 if (!recursive ("%Y-%m-%d"))
927 return NULL;
928 want_xday = 1;
929 break;
930 case 'x':
931 #ifdef _NL_CURRENT
932 if (*decided != raw)
933 {
934 if (!recursive (_NL_CURRENT (LC_TIME, D_FMT)))
935 {
936 if (*decided == loc)
937 return NULL;
938 else
939 rp = rp_backup;
940 }
941 else
942 {
943 if (*decided == not
944 && strcmp (_NL_CURRENT (LC_TIME, D_FMT), HERE_D_FMT))
945 *decided = loc;
946 want_xday = 1;
947 break;
948 }
949 *decided = raw;
950 }
951 #endif
952 /* Fall through. */
953 case 'D':
954 /* Match standard day format. */
955 if (!recursive (HERE_D_FMT))
956 return NULL;
957 want_xday = 1;
958 break;
959 case 'k':
960 case 'H':
961 /* Match hour in 24-hour clock. */
962 get_number (0, 23, 2);
963 tm->tm_hour = val;
964 have_I = 0;
965 break;
966 case 'I':
967 /* Match hour in 12-hour clock. */
968 get_number (1, 12, 2);
969 tm->tm_hour = val % 12;
970 have_I = 1;
971 break;
972 case 'j':
973 /* Match day number of year. */
974 get_number (1, 366, 3);
975 tm->tm_yday = val - 1;
976 have_yday = 1;
977 break;
978 case 'm':
979 /* Match number of month. */
980 get_number (1, 12, 2);
981 tm->tm_mon = val - 1;
982 have_mon = 1;
983 want_xday = 1;
984 break;
985 case 'M':
986 /* Match minute. */
987 get_number (0, 59, 2);
988 tm->tm_min = val;
989 break;
990 case 'n':
991 case 't':
992 /* Match any white space. */
993 while (isspace (*rp))
994 ++rp;
995 break;
996 case 'p':
997 /* Match locale's equivalent of AM/PM. */
998 #ifdef _NL_CURRENT
999 if (*decided != raw)
1000 {
1001 if (match_string (_NL_CURRENT (LC_TIME, AM_STR), rp))
1002 {
1003 if (strcmp (_NL_CURRENT (LC_TIME, AM_STR), HERE_AM_STR))
1004 *decided = loc;
1005 break;
1006 }
1007 if (match_string (_NL_CURRENT (LC_TIME, PM_STR), rp))
1008 {
1009 if (strcmp (_NL_CURRENT (LC_TIME, PM_STR), HERE_PM_STR))
1010 *decided = loc;
1011 is_pm = 1;
1012 break;
1013 }
1014 *decided = raw;
1015 }
1016 #endif
1017 if (!match_string (HERE_AM_STR, rp))
1018 if (match_string (HERE_PM_STR, rp))
1019 is_pm = 1;
1020 else
1021 return NULL;
1022 break;
1023 case 'r':
1024 #ifdef _NL_CURRENT
1025 if (*decided != raw)
1026 {
1027 if (!recursive (_NL_CURRENT (LC_TIME, T_FMT_AMPM)))
1028 {
1029 if (*decided == loc)
1030 return NULL;
1031 else
1032 rp = rp_backup;
1033 }
1034 else
1035 {
1036 if (*decided == not &&
1037 strcmp (_NL_CURRENT (LC_TIME, T_FMT_AMPM),
1038 HERE_T_FMT_AMPM))
1039 *decided = loc;
1040 break;
1041 }
1042 *decided = raw;
1043 }
1044 #endif
1045 if (!recursive (HERE_T_FMT_AMPM))
1046 return NULL;
1047 break;
1048 case 'R':
1049 if (!recursive ("%H:%M"))
1050 return NULL;
1051 break;
1052 case 's':
1053 {
1054 /* The number of seconds may be very high so we cannot use
1055 the `get_number' macro. Instead read the number
1056 character for character and construct the result while
1057 doing this. */
1058 time_t secs = 0;
1059 if (*rp < '0' || *rp > '9')
1060 /* We need at least one digit. */
1061 return NULL;
1062
1063 do
1064 {
1065 secs *= 10;
1066 secs += *rp++ - '0';
1067 }
1068 while (*rp >= '0' && *rp <= '9');
1069
1070 if (localtime_r (&secs, tm) == NULL)
1071 /* Error in function. */
1072 return NULL;
1073 }
1074 break;
1075 case 'S':
1076 get_number (0, 61, 2);
1077 tm->tm_sec = val;
1078 break;
1079 case 'X':
1080 #ifdef _NL_CURRENT
1081 if (*decided != raw)
1082 {
1083 if (!recursive (_NL_CURRENT (LC_TIME, T_FMT)))
1084 {
1085 if (*decided == loc)
1086 return NULL;
1087 else
1088 rp = rp_backup;
1089 }
1090 else
1091 {
1092 if (strcmp (_NL_CURRENT (LC_TIME, T_FMT), HERE_T_FMT))
1093 *decided = loc;
1094 break;
1095 }
1096 *decided = raw;
1097 }
1098 #endif
1099 /* Fall through. */
1100 case 'T':
1101 if (!recursive (HERE_T_FMT))
1102 return NULL;
1103 break;
1104 case 'u':
1105 get_number (1, 7, 1);
1106 tm->tm_wday = val % 7;
1107 have_wday = 1;
1108 break;
1109 case 'g':
1110 get_number (0, 99, 2);
1111 /* XXX This cannot determine any field in TM. */
1112 break;
1113 case 'G':
1114 if (*rp < '0' || *rp > '9')
1115 return NULL;
1116 /* XXX Ignore the number since we would need some more
1117 information to compute a real date. */
1118 do
1119 ++rp;
1120 while (*rp >= '0' && *rp <= '9');
1121 break;
1122 case 'U':
1123 case 'V':
1124 case 'W':
1125 get_number (0, 53, 2);
1126 /* XXX This cannot determine any field in TM without some
1127 information. */
1128 break;
1129 case 'w':
1130 /* Match number of weekday. */
1131 get_number (0, 6, 1);
1132 tm->tm_wday = val;
1133 have_wday = 1;
1134 break;
1135 case 'y':
1136 #ifdef _NL_CURRENT
1137 match_year_in_century:
1138 #endif
1139 /* Match year within century. */
1140 get_number (0, 99, 2);
1141 /* The "Year 2000: The Millennium Rollover" paper suggests that
1142 values in the range 69-99 refer to the twentieth century. */
1143 tm->tm_year = val >= 69 ? val : val + 100;
1144 /* Indicate that we want to use the century, if specified. */
1145 want_century = 1;
1146 want_xday = 1;
1147 break;
1148 case 'Y':
1149 /* Match year including century number. */
1150 get_number (0, 9999, 4);
1151 tm->tm_year = val - 1900;
1152 want_century = 0;
1153 want_xday = 1;
1154 break;
1155 case 'Z':
1156 /* XXX How to handle this? */
1157 break;
1158 case 'E':
1159 #ifdef _NL_CURRENT
1160 switch (*fmt++)
1161 {
1162 case 'c':
1163 /* Match locale's alternate date and time format. */
1164 if (*decided != raw)
1165 {
1166 const char *fmt = _NL_CURRENT (LC_TIME, ERA_D_T_FMT);
1167
1168 if (*fmt == '\0')
1169 fmt = _NL_CURRENT (LC_TIME, D_T_FMT);
1170
1171 if (!recursive (fmt))
1172 {
1173 if (*decided == loc)
1174 return NULL;
1175 else
1176 rp = rp_backup;
1177 }
1178 else
1179 {
1180 if (strcmp (fmt, HERE_D_T_FMT))
1181 *decided = loc;
1182 want_xday = 1;
1183 break;
1184 }
1185 *decided = raw;
1186 }
1187 /* The C locale has no era information, so use the
1188 normal representation. */
1189 if (!recursive (HERE_D_T_FMT))
1190 return NULL;
1191 want_xday = 1;
1192 break;
1193 case 'C':
1194 if (*decided != raw)
1195 {
1196 if (era_cnt >= 0)
1197 {
1198 era = _nl_select_era_entry (era_cnt);
1199 if (match_string (era->era_name, rp))
1200 {
1201 *decided = loc;
1202 break;
1203 }
1204 else
1205 return NULL;
1206 }
1207 else
1208 {
1209 num_eras = _NL_CURRENT_WORD (LC_TIME,
1210 _NL_TIME_ERA_NUM_ENTRIES);
1211 for (era_cnt = 0; era_cnt < (int) num_eras;
1212 ++era_cnt, rp = rp_backup)
1213 {
1214 era = _nl_select_era_entry (era_cnt);
1215 if (match_string (era->era_name, rp))
1216 {
1217 *decided = loc;
1218 break;
1219 }
1220 }
1221 if (era_cnt == (int) num_eras)
1222 {
1223 era_cnt = -1;
1224 if (*decided == loc)
1225 return NULL;
1226 }
1227 else
1228 break;
1229 }
1230
1231 *decided = raw;
1232 }
1233 /* The C locale has no era information, so use the
1234 normal representation. */
1235 goto match_century;
1236 case 'y':
1237 if (*decided == raw)
1238 goto match_year_in_century;
1239
1240 get_number(0, 9999, 4);
1241 tm->tm_year = val;
1242 want_era = 1;
1243 want_xday = 1;
1244 break;
1245 case 'Y':
1246 if (*decided != raw)
1247 {
1248 num_eras = _NL_CURRENT_WORD (LC_TIME,
1249 _NL_TIME_ERA_NUM_ENTRIES);
1250 for (era_cnt = 0; era_cnt < (int) num_eras;
1251 ++era_cnt, rp = rp_backup)
1252 {
1253 era = _nl_select_era_entry (era_cnt);
1254 if (recursive (era->era_format))
1255 break;
1256 }
1257 if (era_cnt == (int) num_eras)
1258 {
1259 era_cnt = -1;
1260 if (*decided == loc)
1261 return NULL;
1262 else
1263 rp = rp_backup;
1264 }
1265 else
1266 {
1267 *decided = loc;
1268 era_cnt = -1;
1269 break;
1270 }
1271
1272 *decided = raw;
1273 }
1274 get_number (0, 9999, 4);
1275 tm->tm_year = val - 1900;
1276 want_century = 0;
1277 want_xday = 1;
1278 break;
1279 case 'x':
1280 if (*decided != raw)
1281 {
1282 const char *fmt = _NL_CURRENT (LC_TIME, ERA_D_FMT);
1283
1284 if (*fmt == '\0')
1285 fmt = _NL_CURRENT (LC_TIME, D_FMT);
1286
1287 if (!recursive (fmt))
1288 {
1289 if (*decided == loc)
1290 return NULL;
1291 else
1292 rp = rp_backup;
1293 }
1294 else
1295 {
1296 if (strcmp (fmt, HERE_D_FMT))
1297 *decided = loc;
1298 break;
1299 }
1300 *decided = raw;
1301 }
1302 if (!recursive (HERE_D_FMT))
1303 return NULL;
1304 break;
1305 case 'X':
1306 if (*decided != raw)
1307 {
1308 const char *fmt = _NL_CURRENT (LC_TIME, ERA_T_FMT);
1309
1310 if (*fmt == '\0')
1311 fmt = _NL_CURRENT (LC_TIME, T_FMT);
1312
1313 if (!recursive (fmt))
1314 {
1315 if (*decided == loc)
1316 return NULL;
1317 else
1318 rp = rp_backup;
1319 }
1320 else
1321 {
1322 if (strcmp (fmt, HERE_T_FMT))
1323 *decided = loc;
1324 break;
1325 }
1326 *decided = raw;
1327 }
1328 if (!recursive (HERE_T_FMT))
1329 return NULL;
1330 break;
1331 default:
1332 return NULL;
1333 }
1334 break;
1335 #else
1336 /* We have no information about the era format. Just use
1337 the normal format. */
1338 if (*fmt != 'c' && *fmt != 'C' && *fmt != 'y' && *fmt != 'Y'
1339 && *fmt != 'x' && *fmt != 'X')
1340 /* This is an illegal format. */
1341 return NULL;
1342
1343 goto start_over;
1344 #endif
1345 case 'O':
1346 switch (*fmt++)
1347 {
1348 case 'd':
1349 case 'e':
1350 /* Match day of month using alternate numeric symbols. */
1351 get_alt_number (1, 31, 2);
1352 tm->tm_mday = val;
1353 have_mday = 1;
1354 want_xday = 1;
1355 break;
1356 case 'H':
1357 /* Match hour in 24-hour clock using alternate numeric
1358 symbols. */
1359 get_alt_number (0, 23, 2);
1360 tm->tm_hour = val;
1361 have_I = 0;
1362 break;
1363 case 'I':
1364 /* Match hour in 12-hour clock using alternate numeric
1365 symbols. */
1366 get_alt_number (1, 12, 2);
1367 tm->tm_hour = val - 1;
1368 have_I = 1;
1369 break;
1370 case 'm':
1371 /* Match month using alternate numeric symbols. */
1372 get_alt_number (1, 12, 2);
1373 tm->tm_mon = val - 1;
1374 have_mon = 1;
1375 want_xday = 1;
1376 break;
1377 case 'M':
1378 /* Match minutes using alternate numeric symbols. */
1379 get_alt_number (0, 59, 2);
1380 tm->tm_min = val;
1381 break;
1382 case 'S':
1383 /* Match seconds using alternate numeric symbols. */
1384 get_alt_number (0, 61, 2);
1385 tm->tm_sec = val;
1386 break;
1387 case 'U':
1388 case 'V':
1389 case 'W':
1390 get_alt_number (0, 53, 2);
1391 /* XXX This cannot determine any field in TM without
1392 further information. */
1393 break;
1394 case 'w':
1395 /* Match number of weekday using alternate numeric symbols. */
1396 get_alt_number (0, 6, 1);
1397 tm->tm_wday = val;
1398 have_wday = 1;
1399 break;
1400 case 'y':
1401 /* Match year within century using alternate numeric symbols. */
1402 get_alt_number (0, 99, 2);
1403 tm->tm_year = val >= 69 ? val : val + 100;
1404 want_xday = 1;
1405 break;
1406 default:
1407 return NULL;
1408 }
1409 break;
1410 default:
1411 return NULL;
1412 }
1413 }
1414
1415 if (have_I && is_pm)
1416 tm->tm_hour += 12;
1417
1418 if (century != -1)
1419 {
1420 if (want_century)
1421 tm->tm_year = tm->tm_year % 100 + (century - 19) * 100;
1422 else
1423 /* Only the century, but not the year. Strange, but so be it. */
1424 tm->tm_year = (century - 19) * 100;
1425 }
1426
1427 #ifdef _NL_CURRENT
1428 if (era_cnt != -1)
1429 {
1430 era = _nl_select_era_entry(era_cnt);
1431 if (want_era)
1432 tm->tm_year = (era->start_date[0]
1433 + ((tm->tm_year - era->offset)
1434 * era->absolute_direction));
1435 else
1436 /* Era start year assumed. */
1437 tm->tm_year = era->start_date[0];
1438 }
1439 else
1440 #endif
1441 if (want_era)
1442 return NULL;
1443
1444 if (want_xday && !have_wday)
1445 {
1446 if ( !(have_mon && have_mday) && have_yday)
1447 {
1448 /* We don't have tm_mon and/or tm_mday, compute them. */
1449 int t_mon = 0;
1450 while (__mon_yday[__isleap(1900 + tm->tm_year)][t_mon] <= tm->tm_yday)
1451 t_mon++;
1452 if (!have_mon)
1453 tm->tm_mon = t_mon - 1;
1454 if (!have_mday)
1455 tm->tm_mday =
1456 (tm->tm_yday
1457 - __mon_yday[__isleap(1900 + tm->tm_year)][t_mon - 1] + 1);
1458 }
1459 day_of_the_week (tm);
1460 }
1461 if (want_xday && !have_yday)
1462 day_of_the_year (tm);
1463
1464 return (char *) rp;
1465 }
1466
1467
1468 char *
1469 msn_strptime (buf, format, tm)
1470 const char *buf;
1471 const char *format;
1472 struct tm *tm;
1473 {
1474 enum locale_status decided;
1475
1476 #ifdef _NL_CURRENT
1477 decided = not;
1478 #else
1479 decided = raw;
1480 #endif
1481 return strptime_internal (buf, format, tm, &decided, -1);
1482 }
1483 #else
1484 #define msn_strptime strptime
1485 #endif