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