1 /* Replacements for routines missing on some systems.
2 Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
4 This file is part of GNU Wget.
6 GNU Wget is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 GNU Wget is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with Wget; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 In addition, as a special exception, the Free Software Foundation
21 gives permission to link the code of its release of Wget with the
22 OpenSSL project's "OpenSSL" library (or with modified versions of it
23 that use the same license as the "OpenSSL" library), and distribute
24 the linked executables. You must obey the GNU General Public License
25 in all respects for all of the code used other than "OpenSSL". If you
26 modify this file, you may extend this exception to your version of the
27 file, but you are not obligated to do so. If you do not wish to do
28 so, delete this exception statement from your version. */
38 #endif /* HAVE_STRING_H */
40 #include <sys/types.h>
49 /* A strerror() clone, for systems that don't have it. */
53 /* This loses on a system without `sys_errlist'. */
54 extern char *sys_errlist[];
55 return sys_errlist[err];
57 #endif /* not HAVE_STRERROR */
59 /* Some systems don't have some str* functions in libc. Here we
60 define them. The same goes for strptime. */
62 #ifndef HAVE_STRCASECMP
64 /* Compare S1 and S2, ignoring case, returning less than, equal to or
65 greater than zero if S1 is lexiographically less than,
66 equal to or greater than S2. */
68 strcasecmp (const char *s1, const char *s2)
70 register const unsigned char *p1 = (const unsigned char *) s1;
71 register const unsigned char *p2 = (const unsigned char *) s2;
88 #endif /* not HAVE_STRCASECMP */
90 #ifndef HAVE_STRNCASECMP
92 /* Compare no more than N characters of S1 and S2,
93 ignoring case, returning less than, equal to or
94 greater than zero if S1 is lexicographically less
95 than, equal to or greater than S2. */
97 strncasecmp (const char *s1, const char *s2, size_t n)
99 register const unsigned char *p1 = (const unsigned char *) s1;
100 register const unsigned char *p2 = (const unsigned char *) s2;
101 unsigned char c1, c2;
103 if (p1 == p2 || n == 0)
108 c1 = TOLOWER (*p1++);
109 c2 = TOLOWER (*p2++);
110 if (c1 == '\0' || c1 != c2)
116 #endif /* not HAVE_STRNCASECMP */
119 /* From GNU libc 2.0.6. */
120 /* Return the first ocurrence of NEEDLE in HAYSTACK. */
122 * My personal strstr() implementation that beats most other algorithms.
123 * Until someone tells me otherwise, I assume that this is the
124 * fastest implementation of strstr() in C.
125 * I deliberately chose not to comment it. You should have at least
126 * as much fun trying to understand it, as I had to write it :-).
128 * Stephen R. van den Berg, berg@pool.informatik.rwth-aachen.de */
129 typedef unsigned chartype;
132 strstr (phaystack, pneedle)
133 const char *phaystack;
136 register const unsigned char *haystack, *needle;
137 register chartype b, c;
139 haystack = (const unsigned char *) phaystack;
140 needle = (const unsigned char *) pneedle;
145 haystack--; /* possible ANSI violation */
163 register const unsigned char *rhaystack, *rneedle;
178 jin: a = *++haystack;
185 rhaystack = haystack-- + 1;
203 while (*rhaystack == a);
205 needle = rneedle; /* took the register-poor approach */
212 return (char*) haystack;
216 #endif /* not HAVE_STRSTR */
219 /* Find the first ocurrence in S of any character in ACCEPT. */
221 strpbrk (const char *s, const char *accept)
225 const char *a = accept;
234 #endif /* HAVE_STRPBRK */
237 /* From GNU libc 2.0. */
239 /* Copyright (C) 1993, 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
240 This file is part of the GNU C Library.
241 Contributed by Paul Eggert (eggert@twinsun.com). */
244 # define HAVE_LIMITS_H 1
245 # define HAVE_LOCALTIME_R 1
246 # define STDC_HEADERS 1
249 /* Assume that leap seconds are possible, unless told otherwise.
250 If the host has a `zic' command with a `-L leapsecondfilename' option,
251 then it supports leap seconds; otherwise it probably doesn't. */
252 #ifndef LEAP_SECONDS_POSSIBLE
253 # define LEAP_SECONDS_POSSIBLE 1
257 # define __P(args) PARAMS (args)
258 #endif /* Not __P. */
265 # define INT_MIN (~0 << (sizeof (int) * CHAR_BIT - 1))
268 # define INT_MAX (~0 - INT_MIN)
272 /* The outer cast to time_t works around a bug in Cray C 5.0.3.0. */
273 # define TIME_T_MIN ((time_t) \
274 (0 < (time_t) -1 ? (time_t) 0 \
275 : ~ (time_t) 0 << (sizeof (time_t) * CHAR_BIT - 1)))
278 # define TIME_T_MAX (~ (time_t) 0 - TIME_T_MIN)
281 #define TM_YEAR_BASE 1900
282 #define EPOCH_YEAR 1970
285 /* Nonzero if YEAR is a leap year (every 4 years,
286 except every 100th isn't, and every 400th is). */
287 # define __isleap(year) \
288 ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
291 /* How many days come before each month (0-12). */
292 /* __mon_yday[][] is common to mktime and strptime implementations.
294 const unsigned short int __mon_yday[2][13];
295 #ifndef NEED_MON_YDAY
296 # define NEED_MON_YDAY
299 static time_t ydhms_tm_diff __P ((int, int, int, int, int, const struct tm *));
300 time_t __mktime_internal __P ((struct tm *,
301 struct tm *(*) (const time_t *, struct tm *),
306 # define localtime_r __localtime_r
308 # if ! HAVE_LOCALTIME_R && ! defined localtime_r
309 /* Approximate localtime_r as best we can in its absence. */
310 # define localtime_r my_mktime_localtime_r
311 static struct tm *localtime_r __P ((const time_t *, struct tm *));
317 struct tm *l = localtime (t);
323 # endif /* ! HAVE_LOCALTIME_R && ! defined (localtime_r) */
327 /* Yield the difference between (YEAR-YDAY HOUR:MIN:SEC) and (*TP),
328 measured in seconds, ignoring leap seconds.
329 YEAR uses the same numbering as TM->tm_year.
330 All values are in range, except possibly YEAR.
331 If overflow occurs, yield the low order bits of the correct answer. */
333 ydhms_tm_diff (year, yday, hour, min, sec, tp)
334 int year, yday, hour, min, sec;
337 /* Compute intervening leap days correctly even if year is negative.
338 Take care to avoid int overflow. time_t overflow is OK, since
339 only the low order bits of the correct time_t answer are needed.
340 Don't convert to time_t until after all divisions are done, since
341 time_t might be unsigned. */
342 int a4 = (year >> 2) + (TM_YEAR_BASE >> 2) - ! (year & 3);
343 int b4 = (tp->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (tp->tm_year & 3);
344 int a100 = a4 / 25 - (a4 % 25 < 0);
345 int b100 = b4 / 25 - (b4 % 25 < 0);
346 int a400 = a100 >> 2;
347 int b400 = b100 >> 2;
348 int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
349 time_t years = year - (time_t) tp->tm_year;
350 time_t days = (365 * years + intervening_leap_days
351 + (yday - tp->tm_yday));
352 return (60 * (60 * (24 * days + (hour - tp->tm_hour))
353 + (min - tp->tm_min))
354 + (sec - tp->tm_sec));
358 static time_t localtime_offset;
360 /* Convert *TP to a time_t value. */
366 /* POSIX.1 8.1.1 requires that whenever mktime() is called, the
367 time zone names contained in the external variable `tzname' shall
368 be set as if the tzset() function had been called. */
372 return __mktime_internal (tp, localtime_r, &localtime_offset);
375 /* Convert *TP to a time_t value, inverting
376 the monotonic and mostly-unit-linear conversion function CONVERT.
377 Use *OFFSET to keep track of a guess at the offset of the result,
378 compared to what the result would be for UTC without leap seconds.
379 If *OFFSET's guess is correct, only one CONVERT call is needed. */
381 __mktime_internal (tp, convert, offset)
383 struct tm *(*convert) __P ((const time_t *, struct tm *));
389 /* The maximum number of probes (calls to CONVERT) should be enough
390 to handle any combinations of time zone rule changes, solar time,
391 and leap seconds. Posix.1 prohibits leap seconds, but some hosts
393 int remaining_probes = 4;
395 /* Time requested. Copy it in case CONVERT modifies *TP; this can
396 occur if TP is localtime's returned value and CONVERT is localtime. */
397 int sec = tp->tm_sec;
398 int min = tp->tm_min;
399 int hour = tp->tm_hour;
400 int mday = tp->tm_mday;
401 int mon = tp->tm_mon;
402 int year_requested = tp->tm_year;
403 int isdst = tp->tm_isdst;
405 /* Ensure that mon is in range, and set year accordingly. */
406 int mon_remainder = mon % 12;
407 int negative_mon_remainder = mon_remainder < 0;
408 int mon_years = mon / 12 - negative_mon_remainder;
409 int year = year_requested + mon_years;
411 /* The other values need not be in range:
412 the remaining code handles minor overflows correctly,
413 assuming int and time_t arithmetic wraps around.
414 Major overflows are caught at the end. */
416 /* Calculate day of year from year, month, and day of month.
417 The result need not be in range. */
418 int yday = ((__mon_yday[__isleap (year + TM_YEAR_BASE)]
419 [mon_remainder + 12 * negative_mon_remainder])
422 int sec_requested = sec;
423 #if LEAP_SECONDS_POSSIBLE
424 /* Handle out-of-range seconds specially,
425 since ydhms_tm_diff assumes every minute has 60 seconds. */
432 /* Invert CONVERT by probing. First assume the same offset as last time.
433 Then repeatedly use the error to improve the guess. */
435 tm.tm_year = EPOCH_YEAR - TM_YEAR_BASE;
436 tm.tm_yday = tm.tm_hour = tm.tm_min = tm.tm_sec = 0;
437 t0 = ydhms_tm_diff (year, yday, hour, min, sec, &tm);
439 for (t = t0 + *offset;
440 (dt = ydhms_tm_diff (year, yday, hour, min, sec, (*convert) (&t, &tm)));
442 if (--remaining_probes == 0)
445 /* Check whether tm.tm_isdst has the requested value, if any. */
446 if (0 <= isdst && 0 <= tm.tm_isdst)
448 int dst_diff = (isdst != 0) - (tm.tm_isdst != 0);
451 /* Move two hours in the direction indicated by the disagreement,
452 probe some more, and switch to a new time if found.
453 The largest known fallback due to daylight savings is two hours:
454 once, in Newfoundland, 1988-10-30 02:00 -> 00:00. */
455 time_t ot = t - 2 * 60 * 60 * dst_diff;
456 while (--remaining_probes != 0)
459 if (! (dt = ydhms_tm_diff (year, yday, hour, min, sec,
460 (*convert) (&ot, &otm))))
467 break; /* Avoid a redundant probe. */
474 #if LEAP_SECONDS_POSSIBLE
475 if (sec_requested != tm.tm_sec)
477 /* Adjust time to reflect the tm_sec requested, not the normalized value.
478 Also, repair any damage from a false match due to a leap second. */
479 t += sec_requested - sec + (sec == 0 && tm.tm_sec == 60);
480 (*convert) (&t, &tm);
484 if (TIME_T_MAX / INT_MAX / 366 / 24 / 60 / 60 < 3)
486 /* time_t isn't large enough to rule out overflows in ydhms_tm_diff,
487 so check for major overflows. A gross check suffices,
488 since if t has overflowed, it is off by a multiple of
489 TIME_T_MAX - TIME_T_MIN + 1. So ignore any component of
490 the difference that is bounded by a small value. */
492 double dyear = (double) year_requested + mon_years - tm.tm_year;
493 double dday = 366 * dyear + mday;
494 double dsec = 60 * (60 * (24 * dday + hour) + min) + sec_requested;
496 if (TIME_T_MAX / 3 - TIME_T_MIN / 3 < (dsec < 0 ? - dsec : dsec))
505 weak_alias (mktime, timelocal)
507 #endif /* not HAVE_MKTIME */
510 #ifndef HAVE_STRPTIME
511 /* From GNU libc 2.1.3. */
512 /* Ulrich, thanks for helping me out with this! --hniksic */
514 /* strptime - Convert a string representation of time to a time value.
515 Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
516 This file is part of the GNU C Library.
517 Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996. */
519 /* XXX This version of the implementation is not really complete.
520 Some of the fields cannot add information alone. But if seeing
521 some of them in the same format (such as year, week and weekday)
522 this is enough information for determining the date. */
525 # define __P(args) PARAMS (args)
528 #if ! HAVE_LOCALTIME_R && ! defined localtime_r
530 # define localtime_r __localtime_r
532 /* Approximate localtime_r as best we can in its absence. */
533 # define localtime_r my_localtime_r
534 static struct tm *localtime_r __P ((const time_t *, struct tm *));
540 struct tm *l = localtime (t);
546 # endif /* ! _LIBC */
547 #endif /* ! HAVE_LOCALTIME_R && ! defined (localtime_r) */
550 #define match_char(ch1, ch2) if (ch1 != ch2) return NULL
551 #if defined __GNUC__ && __GNUC__ >= 2
552 # define match_string(cs1, s2) \
553 ({ size_t len = strlen (cs1); \
554 int result = strncasecmp ((cs1), (s2), len) == 0; \
555 if (result) (s2) += len; \
558 /* Oh come on. Get a reasonable compiler. */
559 # define match_string(cs1, s2) \
560 (strncasecmp ((cs1), (s2), strlen (cs1)) ? 0 : ((s2) += strlen (cs1), 1))
562 /* We intentionally do not use isdigit() for testing because this will
563 lead to problems with the wide character version. */
564 #define get_number(from, to, n) \
570 if (*rp < '0' || *rp > '9') \
574 val += *rp++ - '0'; \
575 } while (--__n > 0 && val * 10 <= to && *rp >= '0' && *rp <= '9'); \
576 if (val < from || val > to) \
580 /* Added check for __GNUC__ extensions here for Wget. --abbotti */
581 # if defined __GNUC__ && __GNUC__ >= 2
582 # define get_alt_number(from, to, n) \
584 __label__ do_normal; \
585 if (*decided != raw) \
587 const char *alts = _NL_CURRENT (LC_TIME, ALT_DIGITS); \
595 while (*alts != '\0') \
597 size_t len = strlen (alts); \
598 if (strncasecmp (alts, rp, len) == 0) \
605 if (*decided == not && ! any) \
607 /* If we haven't read anything it's an error. */ \
610 /* Correct the premature multiplication. */ \
616 } while (--__n > 0 && val * 10 <= to); \
617 if (val < from || val > to) \
623 get_number (from, to, n); \
628 # define get_alt_number(from, to, n) \
630 if (*decided != raw) \
632 const char *alts = _NL_CURRENT (LC_TIME, ALT_DIGITS); \
640 while (*alts != '\0') \
642 size_t len = strlen (alts); \
643 if (strncasecmp (alts, rp, len) == 0) \
650 if (*decided == not && ! any) \
652 /* If we haven't read anything it's an error. */ \
655 /* Correct the premature multiplication. */ \
661 } while (--__n > 0 && val * 10 <= to); \
662 if (val < from || val > to) \
668 get_number (from, to, n); \
671 # endif /* defined __GNUC__ && __GNUC__ >= 2 */
673 # define get_alt_number(from, to, n) \
674 /* We don't have the alternate representation. */ \
675 get_number(from, to, n)
677 #define recursive(new_fmt) \
678 (*(new_fmt) != '\0' \
679 && (rp = strptime_internal (rp, (new_fmt), tm, decided)) != NULL)
683 /* This is defined in locale/C-time.c in the GNU libc. */
684 extern const struct locale_data _nl_C_LC_TIME;
685 extern const unsigned short int __mon_yday[2][13];
687 # define weekday_name (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (DAY_1)].string)
688 # define ab_weekday_name \
689 (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (ABDAY_1)].string)
690 # define month_name (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (MON_1)].string)
691 # define ab_month_name (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (ABMON_1)].string)
692 # define HERE_D_T_FMT (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (D_T_FMT)].string)
693 # define HERE_D_FMT (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (D_FMT)].string)
694 # define HERE_AM_STR (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (AM_STR)].string)
695 # define HERE_PM_STR (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (PM_STR)].string)
696 # define HERE_T_FMT_AMPM \
697 (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (T_FMT_AMPM)].string)
698 # define HERE_T_FMT (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (T_FMT)].string)
700 # define strncasecmp(s1, s2, n) __strncasecmp (s1, s2, n)
702 static char const weekday_name[][10] =
704 "Sunday", "Monday", "Tuesday", "Wednesday",
705 "Thursday", "Friday", "Saturday"
707 static char const ab_weekday_name[][4] =
709 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
711 static char const month_name[][10] =
713 "January", "February", "March", "April", "May", "June",
714 "July", "August", "September", "October", "November", "December"
716 static char const ab_month_name[][4] =
718 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
719 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
721 # define HERE_D_T_FMT "%a %b %e %H:%M:%S %Y"
722 # define HERE_D_FMT "%m/%d/%y"
723 # define HERE_AM_STR "AM"
724 # define HERE_PM_STR "PM"
725 # define HERE_T_FMT_AMPM "%I:%M:%S %p"
726 # define HERE_T_FMT "%H:%M:%S"
728 /* __mon_yday[][] is common to mktime and strptime implementations.
730 const unsigned short int __mon_yday[2][13];
731 # ifndef NEED_MON_YDAY
732 # define NEED_MON_YDAY
736 /* Status of lookup: do we use the locale data or the raw data? */
737 enum locale_status { not, loc, raw };
741 /* Nonzero if YEAR is a leap year (every 4 years,
742 except every 100th isn't, and every 400th is). */
743 # define __isleap(year) \
744 ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
747 /* Compute the day of the week. */
749 day_of_the_week (struct tm *tm)
751 /* We know that January 1st 1970 was a Thursday (= 4). Compute the
752 the difference between this data in the one on TM and so determine
754 int corr_year = 1900 + tm->tm_year - (tm->tm_mon < 2);
756 + (365 * (tm->tm_year - 70))
758 - ((corr_year / 4) / 25) + ((corr_year / 4) % 25 < 0)
759 + (((corr_year / 4) / 25) / 4)
760 + __mon_yday[0][tm->tm_mon]
762 tm->tm_wday = ((wday % 7) + 7) % 7;
765 /* Compute the day of the year. */
767 day_of_the_year (struct tm *tm)
769 tm->tm_yday = (__mon_yday[__isleap (1900 + tm->tm_year)][tm->tm_mon]
770 + (tm->tm_mday - 1));
777 strptime_internal __P ((const char *buf, const char *format, struct tm *tm,
778 enum locale_status *decided));
784 strptime_internal (rp, fmt, tm, decided)
788 enum locale_status *decided;
790 const char *rp_backup;
794 int century, want_century;
795 int have_wday, want_xday;
797 int have_mon, have_mday;
802 have_wday = want_xday = have_yday = have_mon = have_mday = 0;
806 /* A white space in the format string matches 0 more or white
807 space in the input string. */
810 while (ISSPACE (*rp))
816 /* Any character but `%' must be matched by the same character
817 in the iput string. */
820 match_char (*fmt++, *rp++);
826 /* We need this for handling the `E' modifier. */
830 /* Make back up of current processing pointer. */
836 /* Match the `%' character itself. */
837 match_char ('%', *rp++);
841 /* Match day of week. */
842 for (cnt = 0; cnt < 7; ++cnt)
847 if (match_string (_NL_CURRENT (LC_TIME, DAY_1 + cnt), rp))
850 && strcmp (_NL_CURRENT (LC_TIME, DAY_1 + cnt),
855 if (match_string (_NL_CURRENT (LC_TIME, ABDAY_1 + cnt), rp))
858 && strcmp (_NL_CURRENT (LC_TIME, ABDAY_1 + cnt),
859 ab_weekday_name[cnt]))
866 && (match_string (weekday_name[cnt], rp)
867 || match_string (ab_weekday_name[cnt], rp)))
874 /* Does not match a weekday name. */
882 /* Match month name. */
883 for (cnt = 0; cnt < 12; ++cnt)
888 if (match_string (_NL_CURRENT (LC_TIME, MON_1 + cnt), rp))
891 && strcmp (_NL_CURRENT (LC_TIME, MON_1 + cnt),
896 if (match_string (_NL_CURRENT (LC_TIME, ABMON_1 + cnt), rp))
899 && strcmp (_NL_CURRENT (LC_TIME, ABMON_1 + cnt),
906 if (match_string (month_name[cnt], rp)
907 || match_string (ab_month_name[cnt], rp))
914 /* Does not match a month name. */
920 /* Match locale's date and time format. */
924 if (!recursive (_NL_CURRENT (LC_TIME, D_T_FMT)))
933 if (*decided == not &&
934 strcmp (_NL_CURRENT (LC_TIME, D_T_FMT), HERE_D_T_FMT))
942 if (!recursive (HERE_D_T_FMT))
947 /* Match century number. */
948 get_number (0, 99, 2);
954 /* Match day of month. */
955 get_number (1, 31, 2);
961 if (!recursive ("%Y-%m-%d"))
969 if (!recursive (_NL_CURRENT (LC_TIME, D_FMT)))
979 && strcmp (_NL_CURRENT (LC_TIME, D_FMT), HERE_D_FMT))
989 /* Match standard day format. */
990 if (!recursive (HERE_D_FMT))
996 /* Match hour in 24-hour clock. */
997 get_number (0, 23, 2);
1002 /* Match hour in 12-hour clock. */
1003 get_number (1, 12, 2);
1004 tm->tm_hour = val % 12;
1008 /* Match day number of year. */
1009 get_number (1, 366, 3);
1010 tm->tm_yday = val - 1;
1014 /* Match number of month. */
1015 get_number (1, 12, 2);
1016 tm->tm_mon = val - 1;
1022 get_number (0, 59, 2);
1027 /* Match any white space. */
1028 while (ISSPACE (*rp))
1032 /* Match locale's equivalent of AM/PM. */
1034 if (*decided != raw)
1036 if (match_string (_NL_CURRENT (LC_TIME, AM_STR), rp))
1038 if (strcmp (_NL_CURRENT (LC_TIME, AM_STR), HERE_AM_STR))
1042 if (match_string (_NL_CURRENT (LC_TIME, PM_STR), rp))
1044 if (strcmp (_NL_CURRENT (LC_TIME, PM_STR), HERE_PM_STR))
1052 if (!match_string (HERE_AM_STR, rp))
1053 if (match_string (HERE_PM_STR, rp))
1060 if (*decided != raw)
1062 if (!recursive (_NL_CURRENT (LC_TIME, T_FMT_AMPM)))
1064 if (*decided == loc)
1071 if (*decided == not &&
1072 strcmp (_NL_CURRENT (LC_TIME, T_FMT_AMPM),
1080 if (!recursive (HERE_T_FMT_AMPM))
1084 if (!recursive ("%H:%M"))
1089 /* The number of seconds may be very high so we cannot use
1090 the `get_number' macro. Instead read the number
1091 character for character and construct the result while
1094 if (*rp < '0' || *rp > '9')
1095 /* We need at least one digit. */
1101 secs += *rp++ - '0';
1103 while (*rp >= '0' && *rp <= '9');
1105 if (localtime_r (&secs, tm) == NULL)
1106 /* Error in function. */
1111 get_number (0, 61, 2);
1116 if (*decided != raw)
1118 if (!recursive (_NL_CURRENT (LC_TIME, T_FMT)))
1120 if (*decided == loc)
1127 if (strcmp (_NL_CURRENT (LC_TIME, T_FMT), HERE_T_FMT))
1136 if (!recursive (HERE_T_FMT))
1140 get_number (1, 7, 1);
1141 tm->tm_wday = val % 7;
1145 get_number (0, 99, 2);
1146 /* XXX This cannot determine any field in TM. */
1149 if (*rp < '0' || *rp > '9')
1151 /* XXX Ignore the number since we would need some more
1152 information to compute a real date. */
1155 while (*rp >= '0' && *rp <= '9');
1160 get_number (0, 53, 2);
1161 /* XXX This cannot determine any field in TM without some
1165 /* Match number of weekday. */
1166 get_number (0, 6, 1);
1171 /* Match year within century. */
1172 get_number (0, 99, 2);
1173 /* The "Year 2000: The Millennium Rollover" paper suggests that
1174 values in the range 69-99 refer to the twentieth century. */
1175 tm->tm_year = val >= 69 ? val : val + 100;
1176 /* Indicate that we want to use the century, if specified. */
1181 /* Match year including century number. */
1182 get_number (0, 9999, 4);
1183 tm->tm_year = val - 1900;
1188 /* XXX How to handle this? */
1195 /* Match locale's alternate date and time format. */
1196 if (*decided != raw)
1198 const char *fmt = _NL_CURRENT (LC_TIME, ERA_D_T_FMT);
1201 fmt = _NL_CURRENT (LC_TIME, D_T_FMT);
1203 if (!recursive (fmt))
1205 if (*decided == loc)
1212 if (strcmp (fmt, HERE_D_T_FMT))
1219 /* The C locale has no era information, so use the
1220 normal representation. */
1221 if (!recursive (HERE_D_T_FMT))
1228 /* Match name of base year in locale's alternate
1230 /* XXX This is currently not implemented. It should
1231 use the value _NL_CURRENT (LC_TIME, ERA). */
1234 if (*decided != raw)
1236 const char *fmt = _NL_CURRENT (LC_TIME, ERA_D_FMT);
1239 fmt = _NL_CURRENT (LC_TIME, D_FMT);
1241 if (!recursive (fmt))
1243 if (*decided == loc)
1250 if (strcmp (fmt, HERE_D_FMT))
1256 if (!recursive (HERE_D_FMT))
1260 if (*decided != raw)
1262 const char *fmt = _NL_CURRENT (LC_TIME, ERA_T_FMT);
1265 fmt = _NL_CURRENT (LC_TIME, T_FMT);
1267 if (!recursive (fmt))
1269 if (*decided == loc)
1276 if (strcmp (fmt, HERE_T_FMT))
1282 if (!recursive (HERE_T_FMT))
1290 /* We have no information about the era format. Just use
1291 the normal format. */
1292 if (*fmt != 'c' && *fmt != 'C' && *fmt != 'y' && *fmt != 'Y'
1293 && *fmt != 'x' && *fmt != 'X')
1294 /* This is an illegal format. */
1304 /* Match day of month using alternate numeric symbols. */
1305 get_alt_number (1, 31, 2);
1311 /* Match hour in 24-hour clock using alternate numeric
1313 get_alt_number (0, 23, 2);
1318 /* Match hour in 12-hour clock using alternate numeric
1320 get_alt_number (1, 12, 2);
1321 tm->tm_hour = val - 1;
1325 /* Match month using alternate numeric symbols. */
1326 get_alt_number (1, 12, 2);
1327 tm->tm_mon = val - 1;
1332 /* Match minutes using alternate numeric symbols. */
1333 get_alt_number (0, 59, 2);
1337 /* Match seconds using alternate numeric symbols. */
1338 get_alt_number (0, 61, 2);
1344 get_alt_number (0, 53, 2);
1345 /* XXX This cannot determine any field in TM without
1346 further information. */
1349 /* Match number of weekday using alternate numeric symbols. */
1350 get_alt_number (0, 6, 1);
1355 /* Match year within century using alternate numeric symbols. */
1356 get_alt_number (0, 99, 2);
1357 tm->tm_year = val >= 69 ? val : val + 100;
1369 if (have_I && is_pm)
1375 tm->tm_year = tm->tm_year % 100 + (century - 19) * 100;
1377 /* Only the century, but not the year. Strange, but so be it. */
1378 tm->tm_year = (century - 19) * 100;
1381 if (want_xday && !have_wday) {
1382 if ( !(have_mon && have_mday) && have_yday) {
1383 /* we don't have tm_mon and/or tm_mday, compute them */
1385 while (__mon_yday[__isleap(1900 + tm->tm_year)][t_mon] <= tm->tm_yday)
1388 tm->tm_mon = t_mon - 1;
1390 tm->tm_mday = tm->tm_yday - __mon_yday[__isleap(1900 + tm->tm_year)][t_mon - 1] + 1;
1392 day_of_the_week (tm);
1394 if (want_xday && !have_yday)
1395 day_of_the_year (tm);
1402 strptime (buf, format, tm)
1407 enum locale_status decided;
1413 return strptime_internal (buf, format, tm, &decided);
1415 #endif /* not HAVE_STRPTIME */
1417 #ifdef NEED_MON_YDAY
1418 /* __mon_yday[][] is common to mktime and strptime implementations.
1420 const unsigned short int __mon_yday[2][13] =
1423 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
1425 { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
1432 /* A simple usleep implementation based on select(). For Unix and
1433 Unix-like systems. */
1436 usleep (unsigned long usec)
1441 select (0, NULL, NULL, NULL, &tm);
1445 #endif /* not WINDOWS */
1446 #endif /* not HAVE_USLEEP */
1449 #ifndef HAVE_MEMMOVE
1451 memmove (char *dest, const char *source, unsigned length)
1455 /* Moving from low mem to hi mem; start at end. */
1456 for (source += length, dest += length; length; --length)
1457 *--dest = *--source;
1458 else if (source != dest)
1460 /* Moving from hi mem to low mem; start at beginning. */
1461 for (; length; --length)
1462 *dest++ = *source++;
1466 #endif /* not HAVE_MEMMOVE */