Mercurial > pidgin.yaz
comparison libpurple/protocols/msn/msnutils.c @ 20421:983cfc2b04fa
Get rid of the reimplementation of strptime in MSN, nothing was using it.
author | Stu Tomlinson <stu@nosnilmot.com> |
---|---|
date | Sat, 26 May 2007 12:49:49 +0000 |
parents | 599b5a4aebab |
children | b462ef222d28 |
comparison
equal
deleted
inserted
replaced
20420:8aa5e490dbf7 | 20421:983cfc2b04fa |
---|---|
614 | 614 |
615 output[32]='\0'; | 615 output[32]='\0'; |
616 | 616 |
617 // purple_debug_info("MaYuan","chl output{%s}\n",output); | 617 // purple_debug_info("MaYuan","chl output{%s}\n",output); |
618 } | 618 } |
619 | |
620 #if (!defined(_XOPEN_SOURCE))||defined(_WIN32) | |
621 | |
622 #ifndef __P | |
623 # if defined (__GNUC__) || (defined (__STDC__) && __STDC__) | |
624 # define __P(args) args | |
625 # else | |
626 # define __P(args) () | |
627 # endif /* GCC. */ | |
628 #endif /* Not __P. */ | |
629 | |
630 #if defined(HAVE_LOCALTIME_R) && ! HAVE_LOCALTIME_R && ! defined localtime_r | |
631 # ifdef _LIBC | |
632 # define localtime_r __localtime_r | |
633 # else | |
634 /* Approximate localtime_r as best we can in its absence. */ | |
635 # define localtime_r my_localtime_r | |
636 static struct tm *localtime_r __P ((const time_t *, struct tm *)); | |
637 static struct tm * | |
638 localtime_r (t, tp) | |
639 const time_t *t; | |
640 struct tm *tp; | |
641 { | |
642 struct tm *l = localtime (t); | |
643 if (! l) | |
644 return 0; | |
645 *tp = *l; | |
646 return tp; | |
647 } | |
648 # endif /* ! _LIBC */ | |
649 #endif /* ! HAVE_LOCALTIME_R && ! defined (localtime_r) */ | |
650 | |
651 | |
652 #define match_char(ch1, ch2) if (ch1 != ch2) return NULL | |
653 | |
654 #if defined __GNUC__ && __GNUC__ >= 2 | |
655 # define match_string(cs1, s2) \ | |
656 ({ size_t len = strlen (cs1); \ | |
657 int result = strncasecmp ((cs1), (s2), len) == 0; \ | |
658 if (result) (s2) += len; \ | |
659 result; }) | |
660 #else | |
661 /* Oh come on. Get a reasonable compiler. */ | |
662 # define match_string(cs1, s2) \ | |
663 (strncasecmp ((cs1), (s2), strlen (cs1)) ? 0 : ((s2) += strlen (cs1), 1)) | |
664 #endif | |
665 | |
666 /* We intentionally do not use isdigit() for testing because this will | |
667 lead to problems with the wide character version. */ | |
668 #define get_number(from, to, n) \ | |
669 do { \ | |
670 int __n = n; \ | |
671 val = 0; \ | |
672 while (*rp == ' ') \ | |
673 ++rp; \ | |
674 if ((*rp < '0') || (*rp > '9')) \ | |
675 return NULL; \ | |
676 do { \ | |
677 val *= 10; \ | |
678 val += *rp++ - '0'; \ | |
679 } while ((--__n > 0) && (val * 10 <= to) && (*rp >= '0') && (*rp <= '9')); \ | |
680 if ((val < from) || (val > to)) \ | |
681 return NULL; \ | |
682 } while (0) | |
683 | |
684 #ifdef _NL_CURRENT | |
685 # define get_alt_number(from, to, n) \ | |
686 ({ \ | |
687 __label__ do_normal; \ | |
688 if (*decided != raw) \ | |
689 { \ | |
690 const char *alts = _NL_CURRENT (LC_TIME, ALT_DIGITS); \ | |
691 int __n = n; \ | |
692 int any = 0; \ | |
693 while (*rp == ' ') \ | |
694 ++rp; \ | |
695 val = 0; \ | |
696 do { \ | |
697 val *= 10; \ | |
698 while (*alts != '\0') \ | |
699 { \ | |
700 size_t len = strlen (alts); \ | |
701 if (strncasecmp (alts, rp, len) == 0) \ | |
702 break; \ | |
703 alts += len + 1; \ | |
704 ++val; \ | |
705 } \ | |
706 if (*alts == '\0') \ | |
707 { \ | |
708 if (*decided == not && ! any) \ | |
709 goto do_normal; \ | |
710 /* If we haven't read anything it's an error. */ \ | |
711 if (! any) \ | |
712 return NULL; \ | |
713 /* Correct the premature multiplication. */ \ | |
714 val /= 10; \ | |
715 break; \ | |
716 } \ | |
717 else \ | |
718 *decided = loc; \ | |
719 } while (--__n > 0 && val * 10 <= to); \ | |
720 if (val < from || val > to) \ | |
721 return NULL; \ | |
722 } \ | |
723 else \ | |
724 { \ | |
725 do_normal: \ | |
726 get_number (from, to, n); \ | |
727 } \ | |
728 0; \ | |
729 }) | |
730 #else | |
731 # define get_alt_number(from, to, n) \ | |
732 /* We don't have the alternate representation. */ \ | |
733 get_number(from, to, n) | |
734 #endif | |
735 | |
736 #define recursive(new_fmt) \ | |
737 (*(new_fmt) != '\0' \ | |
738 && (rp = strptime_internal (rp, (new_fmt), tm, decided, era_cnt)) != NULL) | |
739 | |
740 | |
741 #ifdef _LIBC | |
742 /* This is defined in locale/C-time.c in the GNU libc. */ | |
743 extern const struct locale_data _nl_C_LC_TIME; | |
744 extern const unsigned short int __mon_yday[2][13]; | |
745 | |
746 # define weekday_name (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (DAY_1)].string) | |
747 # define ab_weekday_name \ | |
748 (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (ABDAY_1)].string) | |
749 # define month_name (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (MON_1)].string) | |
750 # define ab_month_name (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (ABMON_1)].string) | |
751 # define HERE_D_T_FMT (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (D_T_FMT)].string) | |
752 # define HERE_D_FMT (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (D_FMT)].string) | |
753 # define HERE_AM_STR (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (AM_STR)].string) | |
754 # define HERE_PM_STR (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (PM_STR)].string) | |
755 # define HERE_T_FMT_AMPM \ | |
756 (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (T_FMT_AMPM)].string) | |
757 # define HERE_T_FMT (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (T_FMT)].string) | |
758 | |
759 # define strncasecmp(s1, s2, n) __strncasecmp (s1, s2, n) | |
760 #else | |
761 static char const weekday_name[][10] = | |
762 { | |
763 "Sunday", "Monday", "Tuesday", "Wednesday", | |
764 "Thursday", "Friday", "Saturday" | |
765 }; | |
766 static char const ab_weekday_name[][4] = | |
767 { | |
768 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" | |
769 }; | |
770 static char const month_name[][10] = | |
771 { | |
772 "January", "February", "March", "April", "May", "June", | |
773 "July", "August", "September", "October", "November", "December" | |
774 }; | |
775 static char const ab_month_name[][4] = | |
776 { | |
777 "Jan", "Feb", "Mar", "Apr", "May", "Jun", | |
778 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" | |
779 }; | |
780 # define HERE_D_T_FMT "%a %b %e %H:%M:%S %Y" | |
781 # define HERE_D_FMT "%m/%d/%y" | |
782 # define HERE_AM_STR "AM" | |
783 # define HERE_PM_STR "PM" | |
784 # define HERE_T_FMT_AMPM "%I:%M:%S %p" | |
785 # define HERE_T_FMT "%H:%M:%S" | |
786 | |
787 const unsigned short int __mon_yday[2][13] = | |
788 { | |
789 /* Normal years. */ | |
790 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }, | |
791 /* Leap years. */ | |
792 { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 } | |
793 }; | |
794 #endif | |
795 | |
796 /* Status of lookup: do we use the locale data or the raw data? */ | |
797 enum locale_status { not, loc, raw }; | |
798 | |
799 | |
800 #ifndef __isleap | |
801 /* Nonzero if YEAR is a leap year (every 4 years, | |
802 except every 100th isn't, and every 400th is). */ | |
803 # define __isleap(year) \ | |
804 ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0)) | |
805 #endif | |
806 | |
807 /* Compute the day of the week. */ | |
808 static void | |
809 day_of_the_week (struct tm *tm) | |
810 { | |
811 /* We know that January 1st 1970 was a Thursday (= 4). Compute the | |
812 the difference between this data in the one on TM and so determine | |
813 the weekday. */ | |
814 int corr_year = 1900 + tm->tm_year - (tm->tm_mon < 2); | |
815 int wday = (-473 | |
816 + (365 * (tm->tm_year - 70)) | |
817 + (corr_year / 4) | |
818 - ((corr_year / 4) / 25) + ((corr_year / 4) % 25 < 0) | |
819 + (((corr_year / 4) / 25) / 4) | |
820 + __mon_yday[0][tm->tm_mon] | |
821 + tm->tm_mday - 1); | |
822 tm->tm_wday = ((wday % 7) + 7) % 7; | |
823 } | |
824 | |
825 /* Compute the day of the year. */ | |
826 static void | |
827 day_of_the_year (struct tm *tm) | |
828 { | |
829 tm->tm_yday = (__mon_yday[__isleap (1900 + tm->tm_year)][tm->tm_mon] | |
830 + (tm->tm_mday - 1)); | |
831 } | |
832 | |
833 static char * | |
834 #ifdef _LIBC | |
835 internal_function | |
836 #endif | |
837 strptime_internal __P ((const char *rp, const char *fmt, struct tm *tm, | |
838 enum locale_status *decided, int era_cnt)); | |
839 | |
840 static char * | |
841 #ifdef _LIBC | |
842 internal_function | |
843 #endif | |
844 strptime_internal (rp, fmt, tm, decided, era_cnt) | |
845 const char *rp; | |
846 const char *fmt; | |
847 struct tm *tm; | |
848 enum locale_status *decided; | |
849 int era_cnt; | |
850 { | |
851 const char *rp_backup; | |
852 int cnt; | |
853 size_t val; | |
854 int have_I, is_pm; | |
855 int century, want_century; | |
856 int want_era; | |
857 int have_wday, want_xday; | |
858 int have_yday; | |
859 int have_mon, have_mday; | |
860 #ifdef _NL_CURRENT | |
861 size_t num_eras; | |
862 #endif | |
863 struct era_entry *era; | |
864 | |
865 have_I = is_pm = 0; | |
866 century = -1; | |
867 want_century = 0; | |
868 want_era = 0; | |
869 era = NULL; | |
870 | |
871 have_wday = want_xday = have_yday = have_mon = have_mday = 0; | |
872 | |
873 while (*fmt != '\0') | |
874 { | |
875 /* A white space in the format string matches 0 more or white | |
876 space in the input string. */ | |
877 if (isspace (*fmt)) | |
878 { | |
879 while (isspace (*rp)) | |
880 ++rp; | |
881 ++fmt; | |
882 continue; | |
883 } | |
884 | |
885 /* Any character but `%' must be matched by the same character | |
886 in the iput string. */ | |
887 if (*fmt != '%') | |
888 { | |
889 match_char (*fmt++, *rp++); | |
890 continue; | |
891 } | |
892 | |
893 ++fmt; | |
894 #ifndef _NL_CURRENT | |
895 /* We need this for handling the `E' modifier. */ | |
896 start_over: | |
897 #endif | |
898 | |
899 /* Make back up of current processing pointer. */ | |
900 rp_backup = rp; | |
901 | |
902 switch (*fmt++) | |
903 { | |
904 case '%': | |
905 /* Match the `%' character itself. */ | |
906 match_char ('%', *rp++); | |
907 break; | |
908 case 'a': | |
909 case 'A': | |
910 /* Match day of week. */ | |
911 for (cnt = 0; cnt < 7; ++cnt) | |
912 { | |
913 #ifdef _NL_CURRENT | |
914 if (*decided !=raw) | |
915 { | |
916 if (match_string (_NL_CURRENT (LC_TIME, DAY_1 + cnt), rp)) | |
917 { | |
918 if (*decided == not | |
919 && strcmp (_NL_CURRENT (LC_TIME, DAY_1 + cnt), | |
920 weekday_name[cnt])) | |
921 *decided = loc; | |
922 break; | |
923 } | |
924 if (match_string (_NL_CURRENT (LC_TIME, ABDAY_1 + cnt), rp)) | |
925 { | |
926 if (*decided == not | |
927 && strcmp (_NL_CURRENT (LC_TIME, ABDAY_1 + cnt), | |
928 ab_weekday_name[cnt])) | |
929 *decided = loc; | |
930 break; | |
931 } | |
932 } | |
933 #endif | |
934 if (*decided != loc | |
935 && (match_string (weekday_name[cnt], rp) | |
936 || match_string (ab_weekday_name[cnt], rp))) | |
937 { | |
938 *decided = raw; | |
939 break; | |
940 } | |
941 } | |
942 if (cnt == 7) | |
943 /* Does not match a weekday name. */ | |
944 return NULL; | |
945 tm->tm_wday = cnt; | |
946 have_wday = 1; | |
947 break; | |
948 case 'b': | |
949 case 'B': | |
950 case 'h': | |
951 /* Match month name. */ | |
952 for (cnt = 0; cnt < 12; ++cnt) | |
953 { | |
954 #ifdef _NL_CURRENT | |
955 if (*decided !=raw) | |
956 { | |
957 if (match_string (_NL_CURRENT (LC_TIME, MON_1 + cnt), rp)) | |
958 { | |
959 if (*decided == not | |
960 && strcmp (_NL_CURRENT (LC_TIME, MON_1 + cnt), | |
961 month_name[cnt])) | |
962 *decided = loc; | |
963 break; | |
964 } | |
965 if (match_string (_NL_CURRENT (LC_TIME, ABMON_1 + cnt), rp)) | |
966 { | |
967 if (*decided == not | |
968 && strcmp (_NL_CURRENT (LC_TIME, ABMON_1 + cnt), | |
969 ab_month_name[cnt])) | |
970 *decided = loc; | |
971 break; | |
972 } | |
973 } | |
974 #endif | |
975 if (match_string (month_name[cnt], rp) | |
976 || match_string (ab_month_name[cnt], rp)) | |
977 { | |
978 *decided = raw; | |
979 break; | |
980 } | |
981 } | |
982 if (cnt == 12) | |
983 /* Does not match a month name. */ | |
984 return NULL; | |
985 tm->tm_mon = cnt; | |
986 want_xday = 1; | |
987 break; | |
988 case 'c': | |
989 /* Match locale's date and time format. */ | |
990 #ifdef _NL_CURRENT | |
991 if (*decided != raw) | |
992 { | |
993 if (!recursive (_NL_CURRENT (LC_TIME, D_T_FMT))) | |
994 { | |
995 if (*decided == loc) | |
996 return NULL; | |
997 else | |
998 rp = rp_backup; | |
999 } | |
1000 else | |
1001 { | |
1002 if (*decided == not && | |
1003 strcmp (_NL_CURRENT (LC_TIME, D_T_FMT), HERE_D_T_FMT)) | |
1004 *decided = loc; | |
1005 want_xday = 1; | |
1006 break; | |
1007 } | |
1008 *decided = raw; | |
1009 } | |
1010 #endif | |
1011 if (!recursive (HERE_D_T_FMT)) | |
1012 return NULL; | |
1013 want_xday = 1; | |
1014 break; | |
1015 case 'C': | |
1016 /* Match century number. */ | |
1017 #ifdef _NL_CURRENT | |
1018 match_century: | |
1019 #endif | |
1020 get_number (0, 99, 2); | |
1021 century = val; | |
1022 want_xday = 1; | |
1023 break; | |
1024 case 'd': | |
1025 case 'e': | |
1026 /* Match day of month. */ | |
1027 get_number (1, 31, 2); | |
1028 tm->tm_mday = val; | |
1029 have_mday = 1; | |
1030 want_xday = 1; | |
1031 break; | |
1032 case 'F': | |
1033 if (!recursive ("%Y-%m-%d")) | |
1034 return NULL; | |
1035 want_xday = 1; | |
1036 break; | |
1037 case 'x': | |
1038 #ifdef _NL_CURRENT | |
1039 if (*decided != raw) | |
1040 { | |
1041 if (!recursive (_NL_CURRENT (LC_TIME, D_FMT))) | |
1042 { | |
1043 if (*decided == loc) | |
1044 return NULL; | |
1045 else | |
1046 rp = rp_backup; | |
1047 } | |
1048 else | |
1049 { | |
1050 if (*decided == not | |
1051 && strcmp (_NL_CURRENT (LC_TIME, D_FMT), HERE_D_FMT)) | |
1052 *decided = loc; | |
1053 want_xday = 1; | |
1054 break; | |
1055 } | |
1056 *decided = raw; | |
1057 } | |
1058 #endif | |
1059 /* Fall through. */ | |
1060 case 'D': | |
1061 /* Match standard day format. */ | |
1062 if (!recursive (HERE_D_FMT)) | |
1063 return NULL; | |
1064 want_xday = 1; | |
1065 break; | |
1066 case 'k': | |
1067 case 'H': | |
1068 /* Match hour in 24-hour clock. */ | |
1069 get_number (0, 23, 2); | |
1070 tm->tm_hour = val; | |
1071 have_I = 0; | |
1072 break; | |
1073 case 'I': | |
1074 /* Match hour in 12-hour clock. */ | |
1075 get_number (1, 12, 2); | |
1076 tm->tm_hour = val % 12; | |
1077 have_I = 1; | |
1078 break; | |
1079 case 'j': | |
1080 /* Match day number of year. */ | |
1081 get_number (1, 366, 3); | |
1082 tm->tm_yday = val - 1; | |
1083 have_yday = 1; | |
1084 break; | |
1085 case 'm': | |
1086 /* Match number of month. */ | |
1087 get_number (1, 12, 2); | |
1088 tm->tm_mon = val - 1; | |
1089 have_mon = 1; | |
1090 want_xday = 1; | |
1091 break; | |
1092 case 'M': | |
1093 /* Match minute. */ | |
1094 get_number (0, 59, 2); | |
1095 tm->tm_min = val; | |
1096 break; | |
1097 case 'n': | |
1098 case 't': | |
1099 /* Match any white space. */ | |
1100 while (isspace (*rp)) | |
1101 ++rp; | |
1102 break; | |
1103 case 'p': | |
1104 /* Match locale's equivalent of AM/PM. */ | |
1105 #ifdef _NL_CURRENT | |
1106 if (*decided != raw) | |
1107 { | |
1108 if (match_string (_NL_CURRENT (LC_TIME, AM_STR), rp)) | |
1109 { | |
1110 if (strcmp (_NL_CURRENT (LC_TIME, AM_STR), HERE_AM_STR)) | |
1111 *decided = loc; | |
1112 break; | |
1113 } | |
1114 if (match_string (_NL_CURRENT (LC_TIME, PM_STR), rp)) | |
1115 { | |
1116 if (strcmp (_NL_CURRENT (LC_TIME, PM_STR), HERE_PM_STR)) | |
1117 *decided = loc; | |
1118 is_pm = 1; | |
1119 break; | |
1120 } | |
1121 *decided = raw; | |
1122 } | |
1123 #endif | |
1124 if (!match_string (HERE_AM_STR, rp)) | |
1125 if (match_string (HERE_PM_STR, rp)) | |
1126 is_pm = 1; | |
1127 else | |
1128 return NULL; | |
1129 break; | |
1130 case 'r': | |
1131 #ifdef _NL_CURRENT | |
1132 if (*decided != raw) | |
1133 { | |
1134 if (!recursive (_NL_CURRENT (LC_TIME, T_FMT_AMPM))) | |
1135 { | |
1136 if (*decided == loc) | |
1137 return NULL; | |
1138 else | |
1139 rp = rp_backup; | |
1140 } | |
1141 else | |
1142 { | |
1143 if (*decided == not && | |
1144 strcmp (_NL_CURRENT (LC_TIME, T_FMT_AMPM), | |
1145 HERE_T_FMT_AMPM)) | |
1146 *decided = loc; | |
1147 break; | |
1148 } | |
1149 *decided = raw; | |
1150 } | |
1151 #endif | |
1152 if (!recursive (HERE_T_FMT_AMPM)) | |
1153 return NULL; | |
1154 break; | |
1155 case 'R': | |
1156 if (!recursive ("%H:%M")) | |
1157 return NULL; | |
1158 break; | |
1159 case 's': | |
1160 { | |
1161 /* The number of seconds may be very high so we cannot use | |
1162 the `get_number' macro. Instead read the number | |
1163 character for character and construct the result while | |
1164 doing this. */ | |
1165 time_t secs = 0; | |
1166 if (*rp < '0' || *rp > '9') | |
1167 /* We need at least one digit. */ | |
1168 return NULL; | |
1169 | |
1170 do | |
1171 { | |
1172 secs *= 10; | |
1173 secs += *rp++ - '0'; | |
1174 } | |
1175 while (*rp >= '0' && *rp <= '9'); | |
1176 | |
1177 if (localtime_r (&secs, tm) == NULL) | |
1178 /* Error in function. */ | |
1179 return NULL; | |
1180 } | |
1181 break; | |
1182 case 'S': | |
1183 get_number (0, 61, 2); | |
1184 tm->tm_sec = val; | |
1185 break; | |
1186 case 'X': | |
1187 #ifdef _NL_CURRENT | |
1188 if (*decided != raw) | |
1189 { | |
1190 if (!recursive (_NL_CURRENT (LC_TIME, T_FMT))) | |
1191 { | |
1192 if (*decided == loc) | |
1193 return NULL; | |
1194 else | |
1195 rp = rp_backup; | |
1196 } | |
1197 else | |
1198 { | |
1199 if (strcmp (_NL_CURRENT (LC_TIME, T_FMT), HERE_T_FMT)) | |
1200 *decided = loc; | |
1201 break; | |
1202 } | |
1203 *decided = raw; | |
1204 } | |
1205 #endif | |
1206 /* Fall through. */ | |
1207 case 'T': | |
1208 if (!recursive (HERE_T_FMT)) | |
1209 return NULL; | |
1210 break; | |
1211 case 'u': | |
1212 get_number (1, 7, 1); | |
1213 tm->tm_wday = val % 7; | |
1214 have_wday = 1; | |
1215 break; | |
1216 case 'g': | |
1217 get_number (0, 99, 2); | |
1218 /* XXX This cannot determine any field in TM. */ | |
1219 break; | |
1220 case 'G': | |
1221 if (*rp < '0' || *rp > '9') | |
1222 return NULL; | |
1223 /* XXX Ignore the number since we would need some more | |
1224 information to compute a real date. */ | |
1225 do | |
1226 ++rp; | |
1227 while (*rp >= '0' && *rp <= '9'); | |
1228 break; | |
1229 case 'U': | |
1230 case 'V': | |
1231 case 'W': | |
1232 get_number (0, 53, 2); | |
1233 /* XXX This cannot determine any field in TM without some | |
1234 information. */ | |
1235 break; | |
1236 case 'w': | |
1237 /* Match number of weekday. */ | |
1238 get_number (0, 6, 1); | |
1239 tm->tm_wday = val; | |
1240 have_wday = 1; | |
1241 break; | |
1242 case 'y': | |
1243 #ifdef _NL_CURRENT | |
1244 match_year_in_century: | |
1245 #endif | |
1246 /* Match year within century. */ | |
1247 get_number (0, 99, 2); | |
1248 /* The "Year 2000: The Millennium Rollover" paper suggests that | |
1249 values in the range 69-99 refer to the twentieth century. */ | |
1250 tm->tm_year = val >= 69 ? val : val + 100; | |
1251 /* Indicate that we want to use the century, if specified. */ | |
1252 want_century = 1; | |
1253 want_xday = 1; | |
1254 break; | |
1255 case 'Y': | |
1256 /* Match year including century number. */ | |
1257 get_number (0, 9999, 4); | |
1258 tm->tm_year = val - 1900; | |
1259 want_century = 0; | |
1260 want_xday = 1; | |
1261 break; | |
1262 case 'Z': | |
1263 /* XXX How to handle this? */ | |
1264 break; | |
1265 case 'E': | |
1266 #ifdef _NL_CURRENT | |
1267 switch (*fmt++) | |
1268 { | |
1269 case 'c': | |
1270 /* Match locale's alternate date and time format. */ | |
1271 if (*decided != raw) | |
1272 { | |
1273 const char *fmt = _NL_CURRENT (LC_TIME, ERA_D_T_FMT); | |
1274 | |
1275 if (*fmt == '\0') | |
1276 fmt = _NL_CURRENT (LC_TIME, D_T_FMT); | |
1277 | |
1278 if (!recursive (fmt)) | |
1279 { | |
1280 if (*decided == loc) | |
1281 return NULL; | |
1282 else | |
1283 rp = rp_backup; | |
1284 } | |
1285 else | |
1286 { | |
1287 if (strcmp (fmt, HERE_D_T_FMT)) | |
1288 *decided = loc; | |
1289 want_xday = 1; | |
1290 break; | |
1291 } | |
1292 *decided = raw; | |
1293 } | |
1294 /* The C locale has no era information, so use the | |
1295 normal representation. */ | |
1296 if (!recursive (HERE_D_T_FMT)) | |
1297 return NULL; | |
1298 want_xday = 1; | |
1299 break; | |
1300 case 'C': | |
1301 if (*decided != raw) | |
1302 { | |
1303 if (era_cnt >= 0) | |
1304 { | |
1305 era = _nl_select_era_entry (era_cnt); | |
1306 if (match_string (era->era_name, rp)) | |
1307 { | |
1308 *decided = loc; | |
1309 break; | |
1310 } | |
1311 else | |
1312 return NULL; | |
1313 } | |
1314 else | |
1315 { | |
1316 num_eras = _NL_CURRENT_WORD (LC_TIME, | |
1317 _NL_TIME_ERA_NUM_ENTRIES); | |
1318 for (era_cnt = 0; era_cnt < (int) num_eras; | |
1319 ++era_cnt, rp = rp_backup) | |
1320 { | |
1321 era = _nl_select_era_entry (era_cnt); | |
1322 if (match_string (era->era_name, rp)) | |
1323 { | |
1324 *decided = loc; | |
1325 break; | |
1326 } | |
1327 } | |
1328 if (era_cnt == (int) num_eras) | |
1329 { | |
1330 era_cnt = -1; | |
1331 if (*decided == loc) | |
1332 return NULL; | |
1333 } | |
1334 else | |
1335 break; | |
1336 } | |
1337 | |
1338 *decided = raw; | |
1339 } | |
1340 /* The C locale has no era information, so use the | |
1341 normal representation. */ | |
1342 goto match_century; | |
1343 case 'y': | |
1344 if (*decided == raw) | |
1345 goto match_year_in_century; | |
1346 | |
1347 get_number(0, 9999, 4); | |
1348 tm->tm_year = val; | |
1349 want_era = 1; | |
1350 want_xday = 1; | |
1351 break; | |
1352 case 'Y': | |
1353 if (*decided != raw) | |
1354 { | |
1355 num_eras = _NL_CURRENT_WORD (LC_TIME, | |
1356 _NL_TIME_ERA_NUM_ENTRIES); | |
1357 for (era_cnt = 0; era_cnt < (int) num_eras; | |
1358 ++era_cnt, rp = rp_backup) | |
1359 { | |
1360 era = _nl_select_era_entry (era_cnt); | |
1361 if (recursive (era->era_format)) | |
1362 break; | |
1363 } | |
1364 if (era_cnt == (int) num_eras) | |
1365 { | |
1366 era_cnt = -1; | |
1367 if (*decided == loc) | |
1368 return NULL; | |
1369 else | |
1370 rp = rp_backup; | |
1371 } | |
1372 else | |
1373 { | |
1374 *decided = loc; | |
1375 era_cnt = -1; | |
1376 break; | |
1377 } | |
1378 | |
1379 *decided = raw; | |
1380 } | |
1381 get_number (0, 9999, 4); | |
1382 tm->tm_year = val - 1900; | |
1383 want_century = 0; | |
1384 want_xday = 1; | |
1385 break; | |
1386 case 'x': | |
1387 if (*decided != raw) | |
1388 { | |
1389 const char *fmt = _NL_CURRENT (LC_TIME, ERA_D_FMT); | |
1390 | |
1391 if (*fmt == '\0') | |
1392 fmt = _NL_CURRENT (LC_TIME, D_FMT); | |
1393 | |
1394 if (!recursive (fmt)) | |
1395 { | |
1396 if (*decided == loc) | |
1397 return NULL; | |
1398 else | |
1399 rp = rp_backup; | |
1400 } | |
1401 else | |
1402 { | |
1403 if (strcmp (fmt, HERE_D_FMT)) | |
1404 *decided = loc; | |
1405 break; | |
1406 } | |
1407 *decided = raw; | |
1408 } | |
1409 if (!recursive (HERE_D_FMT)) | |
1410 return NULL; | |
1411 break; | |
1412 case 'X': | |
1413 if (*decided != raw) | |
1414 { | |
1415 const char *fmt = _NL_CURRENT (LC_TIME, ERA_T_FMT); | |
1416 | |
1417 if (*fmt == '\0') | |
1418 fmt = _NL_CURRENT (LC_TIME, T_FMT); | |
1419 | |
1420 if (!recursive (fmt)) | |
1421 { | |
1422 if (*decided == loc) | |
1423 return NULL; | |
1424 else | |
1425 rp = rp_backup; | |
1426 } | |
1427 else | |
1428 { | |
1429 if (strcmp (fmt, HERE_T_FMT)) | |
1430 *decided = loc; | |
1431 break; | |
1432 } | |
1433 *decided = raw; | |
1434 } | |
1435 if (!recursive (HERE_T_FMT)) | |
1436 return NULL; | |
1437 break; | |
1438 default: | |
1439 return NULL; | |
1440 } | |
1441 break; | |
1442 #else | |
1443 /* We have no information about the era format. Just use | |
1444 the normal format. */ | |
1445 if (*fmt != 'c' && *fmt != 'C' && *fmt != 'y' && *fmt != 'Y' | |
1446 && *fmt != 'x' && *fmt != 'X') | |
1447 /* This is an illegal format. */ | |
1448 return NULL; | |
1449 | |
1450 goto start_over; | |
1451 #endif | |
1452 case 'O': | |
1453 switch (*fmt++) | |
1454 { | |
1455 case 'd': | |
1456 case 'e': | |
1457 /* Match day of month using alternate numeric symbols. */ | |
1458 get_alt_number (1, 31, 2); | |
1459 tm->tm_mday = val; | |
1460 have_mday = 1; | |
1461 want_xday = 1; | |
1462 break; | |
1463 case 'H': | |
1464 /* Match hour in 24-hour clock using alternate numeric | |
1465 symbols. */ | |
1466 get_alt_number (0, 23, 2); | |
1467 tm->tm_hour = val; | |
1468 have_I = 0; | |
1469 break; | |
1470 case 'I': | |
1471 /* Match hour in 12-hour clock using alternate numeric | |
1472 symbols. */ | |
1473 get_alt_number (1, 12, 2); | |
1474 tm->tm_hour = val - 1; | |
1475 have_I = 1; | |
1476 break; | |
1477 case 'm': | |
1478 /* Match month using alternate numeric symbols. */ | |
1479 get_alt_number (1, 12, 2); | |
1480 tm->tm_mon = val - 1; | |
1481 have_mon = 1; | |
1482 want_xday = 1; | |
1483 break; | |
1484 case 'M': | |
1485 /* Match minutes using alternate numeric symbols. */ | |
1486 get_alt_number (0, 59, 2); | |
1487 tm->tm_min = val; | |
1488 break; | |
1489 case 'S': | |
1490 /* Match seconds using alternate numeric symbols. */ | |
1491 get_alt_number (0, 61, 2); | |
1492 tm->tm_sec = val; | |
1493 break; | |
1494 case 'U': | |
1495 case 'V': | |
1496 case 'W': | |
1497 get_alt_number (0, 53, 2); | |
1498 /* XXX This cannot determine any field in TM without | |
1499 further information. */ | |
1500 break; | |
1501 case 'w': | |
1502 /* Match number of weekday using alternate numeric symbols. */ | |
1503 get_alt_number (0, 6, 1); | |
1504 tm->tm_wday = val; | |
1505 have_wday = 1; | |
1506 break; | |
1507 case 'y': | |
1508 /* Match year within century using alternate numeric symbols. */ | |
1509 get_alt_number (0, 99, 2); | |
1510 tm->tm_year = val >= 69 ? val : val + 100; | |
1511 want_xday = 1; | |
1512 break; | |
1513 default: | |
1514 return NULL; | |
1515 } | |
1516 break; | |
1517 default: | |
1518 return NULL; | |
1519 } | |
1520 } | |
1521 | |
1522 if (have_I && is_pm) | |
1523 tm->tm_hour += 12; | |
1524 | |
1525 if (century != -1) | |
1526 { | |
1527 if (want_century) | |
1528 tm->tm_year = tm->tm_year % 100 + (century - 19) * 100; | |
1529 else | |
1530 /* Only the century, but not the year. Strange, but so be it. */ | |
1531 tm->tm_year = (century - 19) * 100; | |
1532 } | |
1533 | |
1534 #ifdef _NL_CURRENT | |
1535 if (era_cnt != -1) | |
1536 { | |
1537 era = _nl_select_era_entry(era_cnt); | |
1538 if (want_era) | |
1539 tm->tm_year = (era->start_date[0] | |
1540 + ((tm->tm_year - era->offset) | |
1541 * era->absolute_direction)); | |
1542 else | |
1543 /* Era start year assumed. */ | |
1544 tm->tm_year = era->start_date[0]; | |
1545 } | |
1546 else | |
1547 #endif | |
1548 if (want_era) | |
1549 return NULL; | |
1550 | |
1551 if (want_xday && !have_wday) | |
1552 { | |
1553 if ( !(have_mon && have_mday) && have_yday) | |
1554 { | |
1555 /* We don't have tm_mon and/or tm_mday, compute them. */ | |
1556 int t_mon = 0; | |
1557 while (__mon_yday[__isleap(1900 + tm->tm_year)][t_mon] <= tm->tm_yday) | |
1558 t_mon++; | |
1559 if (!have_mon) | |
1560 tm->tm_mon = t_mon - 1; | |
1561 if (!have_mday) | |
1562 tm->tm_mday = | |
1563 (tm->tm_yday | |
1564 - __mon_yday[__isleap(1900 + tm->tm_year)][t_mon - 1] + 1); | |
1565 } | |
1566 day_of_the_week (tm); | |
1567 } | |
1568 if (want_xday && !have_yday) | |
1569 day_of_the_year (tm); | |
1570 | |
1571 return (char *) rp; | |
1572 } | |
1573 | |
1574 | |
1575 char * | |
1576 msn_strptime (buf, format, tm) | |
1577 const char *buf; | |
1578 const char *format; | |
1579 struct tm *tm; | |
1580 { | |
1581 enum locale_status decided; | |
1582 | |
1583 #ifdef _NL_CURRENT | |
1584 decided = not; | |
1585 #else | |
1586 decided = raw; | |
1587 #endif | |
1588 return strptime_internal (buf, format, tm, &decided, -1); | |
1589 } | |
1590 #else | |
1591 #define msn_strptime strptime | |
1592 #endif |