1 /* Replacements for routines missing on some systems.
2 Copyright (C) 1996-2005 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 Foundation, Inc.,
18 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 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. */
45 /* Some systems lack certain functions normally taken for granted.
46 For example, Windows doesn't have strptime, and some systems don't
47 have a usable fnmatch. This file should contain fallback
48 implementations of such missing functions. It should *not* define
49 new Wget-specific interfaces -- those should be placed in utils.c
52 /* strcasecmp and strncasecmp apparently originated with BSD 4.4.
53 SUSv3 seems to be the only standard out there (that I can find)
54 that requires their existence, so in theory there might be systems
55 still in use that lack them. Note that these don't get defined
56 under Windows because mswindows.h defines them to the equivalent
57 Windows functions stricmp and strnicmp. */
59 #ifndef HAVE_STRCASECMP
61 /* Compare S1 and S2, ignoring case, returning less than, equal to or
62 greater than zero if S1 is lexiographically less than,
63 equal to or greater than S2. */
65 strcasecmp (const char *s1, const char *s2)
67 register const unsigned char *p1 = (const unsigned char *) s1;
68 register const unsigned char *p2 = (const unsigned char *) s2;
85 #endif /* not HAVE_STRCASECMP */
87 #ifndef HAVE_STRNCASECMP
89 /* Compare no more than N characters of S1 and S2,
90 ignoring case, returning less than, equal to or
91 greater than zero if S1 is lexicographically less
92 than, equal to or greater than S2. */
94 strncasecmp (const char *s1, const char *s2, size_t n)
96 register const unsigned char *p1 = (const unsigned char *) s1;
97 register const unsigned char *p2 = (const unsigned char *) s2;
100 if (p1 == p2 || n == 0)
105 c1 = TOLOWER (*p1++);
106 c2 = TOLOWER (*p2++);
107 if (c1 == '\0' || c1 != c2)
113 #endif /* not HAVE_STRNCASECMP */
115 /* strptime is required by POSIX, but it is missing from Windows,
116 which means we must keep a fallback implementation. It is
117 reportedly missing or broken on many older systems as well. */
119 #ifndef HAVE_STRPTIME
120 /* From GNU libc 2.1.3. */
121 /* Ulrich, thanks for helping me out with this! --hniksic */
123 /* strptime - Convert a string representation of time to a time value.
124 Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
125 This file is part of the GNU C Library.
126 Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996. */
128 /* XXX This version of the implementation is not really complete.
129 Some of the fields cannot add information alone. But if seeing
130 some of them in the same format (such as year, week and weekday)
131 this is enough information for determining the date. */
134 # define __P(args) args
137 #if ! HAVE_LOCALTIME_R && ! defined localtime_r
139 # define localtime_r __localtime_r
141 /* Approximate localtime_r as best we can in its absence. */
142 # define localtime_r my_localtime_r
143 static struct tm *localtime_r __P ((const time_t *, struct tm *));
149 struct tm *l = localtime (t);
155 # endif /* ! _LIBC */
156 #endif /* ! HAVE_LOCALTIME_R && ! defined (localtime_r) */
159 #define match_char(ch1, ch2) if (ch1 != ch2) return NULL
160 #if defined __GNUC__ && __GNUC__ >= 2
161 # define match_string(cs1, s2) \
162 ({ size_t len = strlen (cs1); \
163 int result = strncasecmp ((cs1), (s2), len) == 0; \
164 if (result) (s2) += len; \
167 /* Oh come on. Get a reasonable compiler. */
168 # define match_string(cs1, s2) \
169 (strncasecmp ((cs1), (s2), strlen (cs1)) ? 0 : ((s2) += strlen (cs1), 1))
171 /* We intentionally do not use isdigit() for testing because this will
172 lead to problems with the wide character version. */
173 #define get_number(from, to, n) \
179 if (*rp < '0' || *rp > '9') \
183 val += *rp++ - '0'; \
184 } while (--__n > 0 && val * 10 <= to && *rp >= '0' && *rp <= '9'); \
185 if (val < from || val > to) \
189 /* Added check for __GNUC__ extensions here for Wget. --abbotti */
190 # if defined __GNUC__ && __GNUC__ >= 2
191 # define get_alt_number(from, to, n) \
193 __label__ do_normal; \
194 if (*decided != raw) \
196 const char *alts = _NL_CURRENT (LC_TIME, ALT_DIGITS); \
204 while (*alts != '\0') \
206 size_t len = strlen (alts); \
207 if (strncasecmp (alts, rp, len) == 0) \
214 if (*decided == not && ! any) \
216 /* If we haven't read anything it's an error. */ \
219 /* Correct the premature multiplication. */ \
225 } while (--__n > 0 && val * 10 <= to); \
226 if (val < from || val > to) \
232 get_number (from, to, n); \
237 # define get_alt_number(from, to, n) \
239 if (*decided != raw) \
241 const char *alts = _NL_CURRENT (LC_TIME, ALT_DIGITS); \
249 while (*alts != '\0') \
251 size_t len = strlen (alts); \
252 if (strncasecmp (alts, rp, len) == 0) \
259 if (*decided == not && ! any) \
261 /* If we haven't read anything it's an error. */ \
264 /* Correct the premature multiplication. */ \
270 } while (--__n > 0 && val * 10 <= to); \
271 if (val < from || val > to) \
277 get_number (from, to, n); \
280 # endif /* defined __GNUC__ && __GNUC__ >= 2 */
282 # define get_alt_number(from, to, n) \
283 /* We don't have the alternate representation. */ \
284 get_number(from, to, n)
286 #define recursive(new_fmt) \
287 (*(new_fmt) != '\0' \
288 && (rp = strptime_internal (rp, (new_fmt), tm, decided)) != NULL)
292 /* This is defined in locale/C-time.c in the GNU libc. */
293 extern const struct locale_data _nl_C_LC_TIME;
294 extern const unsigned short int __mon_yday[2][13];
296 # define weekday_name (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (DAY_1)].string)
297 # define ab_weekday_name \
298 (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (ABDAY_1)].string)
299 # define month_name (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (MON_1)].string)
300 # define ab_month_name (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (ABMON_1)].string)
301 # define HERE_D_T_FMT (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (D_T_FMT)].string)
302 # define HERE_D_FMT (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (D_FMT)].string)
303 # define HERE_AM_STR (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (AM_STR)].string)
304 # define HERE_PM_STR (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (PM_STR)].string)
305 # define HERE_T_FMT_AMPM \
306 (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (T_FMT_AMPM)].string)
307 # define HERE_T_FMT (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (T_FMT)].string)
309 # define strncasecmp(s1, s2, n) __strncasecmp (s1, s2, n)
311 static char const weekday_name[][10] =
313 "Sunday", "Monday", "Tuesday", "Wednesday",
314 "Thursday", "Friday", "Saturday"
316 static char const ab_weekday_name[][4] =
318 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
320 static char const month_name[][10] =
322 "January", "February", "March", "April", "May", "June",
323 "July", "August", "September", "October", "November", "December"
325 static char const ab_month_name[][4] =
327 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
328 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
330 # define HERE_D_T_FMT "%a %b %e %H:%M:%S %Y"
331 # define HERE_D_FMT "%m/%d/%y"
332 # define HERE_AM_STR "AM"
333 # define HERE_PM_STR "PM"
334 # define HERE_T_FMT_AMPM "%I:%M:%S %p"
335 # define HERE_T_FMT "%H:%M:%S"
337 const unsigned short int __mon_yday[2][13];
338 # ifndef NEED_MON_YDAY
339 # define NEED_MON_YDAY
343 /* Status of lookup: do we use the locale data or the raw data? */
344 enum locale_status { not, loc, raw };
348 /* Nonzero if YEAR is a leap year (every 4 years,
349 except every 100th isn't, and every 400th is). */
350 # define __isleap(year) \
351 ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
354 /* Compute the day of the week. */
356 day_of_the_week (struct tm *tm)
358 /* We know that January 1st 1970 was a Thursday (= 4). Compute the
359 the difference between this data in the one on TM and so determine
361 int corr_year = 1900 + tm->tm_year - (tm->tm_mon < 2);
363 + (365 * (tm->tm_year - 70))
365 - ((corr_year / 4) / 25) + ((corr_year / 4) % 25 < 0)
366 + (((corr_year / 4) / 25) / 4)
367 + __mon_yday[0][tm->tm_mon]
369 tm->tm_wday = ((wday % 7) + 7) % 7;
372 /* Compute the day of the year. */
374 day_of_the_year (struct tm *tm)
376 tm->tm_yday = (__mon_yday[__isleap (1900 + tm->tm_year)][tm->tm_mon]
377 + (tm->tm_mday - 1));
384 strptime_internal __P ((const char *buf, const char *format, struct tm *tm,
385 enum locale_status *decided));
391 strptime_internal (rp, fmt, tm, decided)
395 enum locale_status *decided;
398 const char *rp_backup;
403 int century, want_century;
404 int have_wday, want_xday;
406 int have_mon, have_mday;
411 have_wday = want_xday = have_yday = have_mon = have_mday = 0;
415 /* A white space in the format string matches 0 more or white
416 space in the input string. */
419 while (ISSPACE (*rp))
425 /* Any character but `%' must be matched by the same character
426 in the iput string. */
429 match_char (*fmt++, *rp++);
435 /* We need this for handling the `E' modifier. */
440 /* Make back up of current processing pointer. */
447 /* Match the `%' character itself. */
448 match_char ('%', *rp++);
452 /* Match day of week. */
453 for (cnt = 0; cnt < 7; ++cnt)
458 if (match_string (_NL_CURRENT (LC_TIME, DAY_1 + cnt), rp))
461 && strcmp (_NL_CURRENT (LC_TIME, DAY_1 + cnt),
466 if (match_string (_NL_CURRENT (LC_TIME, ABDAY_1 + cnt), rp))
469 && strcmp (_NL_CURRENT (LC_TIME, ABDAY_1 + cnt),
470 ab_weekday_name[cnt]))
477 && (match_string (weekday_name[cnt], rp)
478 || match_string (ab_weekday_name[cnt], rp)))
485 /* Does not match a weekday name. */
493 /* Match month name. */
494 for (cnt = 0; cnt < 12; ++cnt)
499 if (match_string (_NL_CURRENT (LC_TIME, MON_1 + cnt), rp))
502 && strcmp (_NL_CURRENT (LC_TIME, MON_1 + cnt),
507 if (match_string (_NL_CURRENT (LC_TIME, ABMON_1 + cnt), rp))
510 && strcmp (_NL_CURRENT (LC_TIME, ABMON_1 + cnt),
517 if (match_string (month_name[cnt], rp)
518 || match_string (ab_month_name[cnt], rp))
525 /* Does not match a month name. */
531 /* Match locale's date and time format. */
535 if (!recursive (_NL_CURRENT (LC_TIME, D_T_FMT)))
544 if (*decided == not &&
545 strcmp (_NL_CURRENT (LC_TIME, D_T_FMT), HERE_D_T_FMT))
553 if (!recursive (HERE_D_T_FMT))
558 /* Match century number. */
559 get_number (0, 99, 2);
565 /* Match day of month. */
566 get_number (1, 31, 2);
572 if (!recursive ("%Y-%m-%d"))
580 if (!recursive (_NL_CURRENT (LC_TIME, D_FMT)))
590 && strcmp (_NL_CURRENT (LC_TIME, D_FMT), HERE_D_FMT))
600 /* Match standard day format. */
601 if (!recursive (HERE_D_FMT))
607 /* Match hour in 24-hour clock. */
608 get_number (0, 23, 2);
613 /* Match hour in 12-hour clock. */
614 get_number (1, 12, 2);
615 tm->tm_hour = val % 12;
619 /* Match day number of year. */
620 get_number (1, 366, 3);
621 tm->tm_yday = val - 1;
625 /* Match number of month. */
626 get_number (1, 12, 2);
627 tm->tm_mon = val - 1;
633 get_number (0, 59, 2);
638 /* Match any white space. */
639 while (ISSPACE (*rp))
643 /* Match locale's equivalent of AM/PM. */
647 if (match_string (_NL_CURRENT (LC_TIME, AM_STR), rp))
649 if (strcmp (_NL_CURRENT (LC_TIME, AM_STR), HERE_AM_STR))
653 if (match_string (_NL_CURRENT (LC_TIME, PM_STR), rp))
655 if (strcmp (_NL_CURRENT (LC_TIME, PM_STR), HERE_PM_STR))
663 if (!match_string (HERE_AM_STR, rp))
665 if (match_string (HERE_PM_STR, rp))
675 if (!recursive (_NL_CURRENT (LC_TIME, T_FMT_AMPM)))
684 if (*decided == not &&
685 strcmp (_NL_CURRENT (LC_TIME, T_FMT_AMPM),
693 if (!recursive (HERE_T_FMT_AMPM))
697 if (!recursive ("%H:%M"))
702 /* The number of seconds may be very high so we cannot use
703 the `get_number' macro. Instead read the number
704 character for character and construct the result while
707 if (*rp < '0' || *rp > '9')
708 /* We need at least one digit. */
716 while (*rp >= '0' && *rp <= '9');
718 if (localtime_r (&secs, tm) == NULL)
719 /* Error in function. */
724 get_number (0, 61, 2);
731 if (!recursive (_NL_CURRENT (LC_TIME, T_FMT)))
740 if (strcmp (_NL_CURRENT (LC_TIME, T_FMT), HERE_T_FMT))
749 if (!recursive (HERE_T_FMT))
753 get_number (1, 7, 1);
754 tm->tm_wday = val % 7;
758 get_number (0, 99, 2);
759 /* XXX This cannot determine any field in TM. */
762 if (*rp < '0' || *rp > '9')
764 /* XXX Ignore the number since we would need some more
765 information to compute a real date. */
768 while (*rp >= '0' && *rp <= '9');
773 get_number (0, 53, 2);
774 /* XXX This cannot determine any field in TM without some
778 /* Match number of weekday. */
779 get_number (0, 6, 1);
784 /* Match year within century. */
785 get_number (0, 99, 2);
786 /* The "Year 2000: The Millennium Rollover" paper suggests that
787 values in the range 69-99 refer to the twentieth century. */
788 tm->tm_year = val >= 69 ? val : val + 100;
789 /* Indicate that we want to use the century, if specified. */
794 /* Match year including century number. */
795 get_number (0, 9999, 4);
796 tm->tm_year = val - 1900;
801 /* XXX How to handle this? */
808 /* Match locale's alternate date and time format. */
811 const char *fmt = _NL_CURRENT (LC_TIME, ERA_D_T_FMT);
814 fmt = _NL_CURRENT (LC_TIME, D_T_FMT);
816 if (!recursive (fmt))
825 if (strcmp (fmt, HERE_D_T_FMT))
832 /* The C locale has no era information, so use the
833 normal representation. */
834 if (!recursive (HERE_D_T_FMT))
841 /* Match name of base year in locale's alternate
843 /* XXX This is currently not implemented. It should
844 use the value _NL_CURRENT (LC_TIME, ERA). */
849 const char *fmt = _NL_CURRENT (LC_TIME, ERA_D_FMT);
852 fmt = _NL_CURRENT (LC_TIME, D_FMT);
854 if (!recursive (fmt))
863 if (strcmp (fmt, HERE_D_FMT))
869 if (!recursive (HERE_D_FMT))
875 const char *fmt = _NL_CURRENT (LC_TIME, ERA_T_FMT);
878 fmt = _NL_CURRENT (LC_TIME, T_FMT);
880 if (!recursive (fmt))
889 if (strcmp (fmt, HERE_T_FMT))
895 if (!recursive (HERE_T_FMT))
903 /* We have no information about the era format. Just use
904 the normal format. */
905 if (*fmt != 'c' && *fmt != 'C' && *fmt != 'y' && *fmt != 'Y'
906 && *fmt != 'x' && *fmt != 'X')
907 /* This is an illegal format. */
917 /* Match day of month using alternate numeric symbols. */
918 get_alt_number (1, 31, 2);
924 /* Match hour in 24-hour clock using alternate numeric
926 get_alt_number (0, 23, 2);
931 /* Match hour in 12-hour clock using alternate numeric
933 get_alt_number (1, 12, 2);
934 tm->tm_hour = val - 1;
938 /* Match month using alternate numeric symbols. */
939 get_alt_number (1, 12, 2);
940 tm->tm_mon = val - 1;
945 /* Match minutes using alternate numeric symbols. */
946 get_alt_number (0, 59, 2);
950 /* Match seconds using alternate numeric symbols. */
951 get_alt_number (0, 61, 2);
957 get_alt_number (0, 53, 2);
958 /* XXX This cannot determine any field in TM without
959 further information. */
962 /* Match number of weekday using alternate numeric symbols. */
963 get_alt_number (0, 6, 1);
968 /* Match year within century using alternate numeric symbols. */
969 get_alt_number (0, 99, 2);
970 tm->tm_year = val >= 69 ? val : val + 100;
988 tm->tm_year = tm->tm_year % 100 + (century - 19) * 100;
990 /* Only the century, but not the year. Strange, but so be it. */
991 tm->tm_year = (century - 19) * 100;
994 if (want_xday && !have_wday) {
995 if ( !(have_mon && have_mday) && have_yday) {
996 /* we don't have tm_mon and/or tm_mday, compute them */
998 while (__mon_yday[__isleap(1900 + tm->tm_year)][t_mon] <= tm->tm_yday)
1001 tm->tm_mon = t_mon - 1;
1003 tm->tm_mday = tm->tm_yday - __mon_yday[__isleap(1900 + tm->tm_year)][t_mon - 1] + 1;
1005 day_of_the_week (tm);
1007 if (want_xday && !have_yday)
1008 day_of_the_year (tm);
1015 strptime (buf, format, tm)
1020 enum locale_status decided;
1026 return strptime_internal (buf, format, tm, &decided);
1028 #endif /* not HAVE_STRPTIME */
1030 #ifdef NEED_MON_YDAY
1031 const unsigned short int __mon_yday[2][13] =
1034 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
1036 { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
1040 /* fnmatch is required by POSIX, but we include an implementation for
1041 the sake of systems that don't have it, most notably Windows. Some
1042 systems do have fnmatch, but Apache's installation process installs
1043 its own fnmatch.h (incompatible with the system one!) in a system
1044 include directory, effectively rendering fnmatch unusable. This
1045 has been fixed with Apache 2, where fnmatch has been moved to apr
1046 and given a prefix, but many systems out there are still (as of
1047 this writing in 2005) broken and we must cater to them.
1049 Additionally, according to some conventional wisdom, many
1050 historical implementations of fnmatch are buggy and unreliable. If
1051 yours is such, undefine SYSTEM_FNMATCH in sysdep.h and tell us
1054 #ifndef SYSTEM_FNMATCH
1056 #define __FNM_FLAGS (FNM_PATHNAME | FNM_NOESCAPE | FNM_PERIOD)
1058 /* Match STRING against the filename pattern PATTERN, returning zero
1059 if it matches, FNM_NOMATCH if not. This implementation comes from
1060 an earlier version of GNU Bash. (It doesn't make sense to update
1061 it with a newer version because those versions add a lot of
1062 features Wget doesn't use or care about.) */
1065 fnmatch (const char *pattern, const char *string, int flags)
1067 register const char *p = pattern, *n = string;
1070 if ((flags & ~__FNM_FLAGS) != 0)
1076 while ((c = *p++) != '\0')
1082 return (FNM_NOMATCH);
1083 else if ((flags & FNM_PATHNAME) && *n == '/')
1084 return (FNM_NOMATCH);
1085 else if ((flags & FNM_PERIOD) && *n == '.' &&
1086 (n == string || ((flags & FNM_PATHNAME) && n[-1] == '/')))
1087 return (FNM_NOMATCH);
1091 if (!(flags & FNM_NOESCAPE))
1094 return (FNM_NOMATCH);
1098 if ((flags & FNM_PERIOD) && *n == '.' &&
1099 (n == string || ((flags & FNM_PATHNAME) && n[-1] == '/')))
1100 return (FNM_NOMATCH);
1102 for (c = *p++; c == '?' || c == '*'; c = *p++, ++n)
1103 if (((flags & FNM_PATHNAME) && *n == '/') ||
1104 (c == '?' && *n == '\0'))
1105 return (FNM_NOMATCH);
1111 char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c;
1112 for (--p; *n != '\0'; ++n)
1113 if ((c == '[' || *n == c1) &&
1114 fnmatch (p, n, flags & ~FNM_PERIOD) == 0)
1116 return (FNM_NOMATCH);
1121 /* Nonzero if the sense of the character class is
1126 return (FNM_NOMATCH);
1128 if ((flags & FNM_PERIOD) && *n == '.' &&
1129 (n == string || ((flags & FNM_PATHNAME) && n[-1] == '/')))
1130 return (FNM_NOMATCH);
1132 /* Make sure there is a closing `]'. If there isn't,
1133 the `[' is just a character to be matched. */
1135 register const char *np;
1137 for (np = p; np && *np && *np != ']'; np++)
1143 return (FNM_NOMATCH);
1148 not = (*p == '!' || *p == '^');
1155 register char cstart = c, cend = c;
1157 if (!(flags & FNM_NOESCAPE) && c == '\\')
1158 cstart = cend = *p++;
1161 /* [ (unterminated) loses. */
1162 return (FNM_NOMATCH);
1166 if ((flags & FNM_PATHNAME) && c == '/')
1167 /* [/] can never match. */
1168 return (FNM_NOMATCH);
1170 if (c == '-' && *p != ']')
1173 if (!(flags & FNM_NOESCAPE) && cend == '\\')
1176 return (FNM_NOMATCH);
1180 if (*n >= cstart && *n <= cend)
1187 return (FNM_NOMATCH);
1193 /* Skip the rest of the [...] that already matched. */
1197 /* [... (unterminated) loses. */
1198 return (FNM_NOMATCH);
1201 if (!(flags & FNM_NOESCAPE) && c == '\\')
1202 /* 1003.2d11 is unclear if this is right. %%% */
1206 return (FNM_NOMATCH);
1212 return (FNM_NOMATCH);
1221 return (FNM_NOMATCH);
1224 #endif /* not SYSTEM_FNMATCH */
1227 /* timegm is a GNU extension, but lately also available on *BSD
1228 systems and possibly elsewhere. */
1230 /* True if YEAR is a leap year. */
1231 #define ISLEAP(year) \
1232 ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
1234 /* Number of leap years in the range [y1, y2). */
1235 #define LEAPYEARS(y1, y2) \
1236 ((y2-1)/4 - (y1-1)/4) - ((y2-1)/100 - (y1-1)/100) + ((y2-1)/400 - (y1-1)/400)
1238 /* Inverse of gmtime: converts struct tm to time_t, assuming the data
1239 in tm is UTC rather than local timezone. This implementation
1240 returns the number of seconds elapsed since midnight 1970-01-01,
1241 converted to time_t. */
1244 timegm (struct tm *t)
1246 static const unsigned short int month_to_days[][13] = {
1247 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }, /* normal */
1248 { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 } /* leap */
1250 const int year = 1900 + t->tm_year;
1251 unsigned long secs; /* until 2106-02-07 for 32-bit unsigned long */
1257 days = 365 * (year - 1970);
1258 /* Take into account leap years between 1970 and YEAR, not counting
1260 days += LEAPYEARS (1970, year);
1261 if (t->tm_mon < 0 || t->tm_mon >= 12)
1263 days += month_to_days[ISLEAP (year)][t->tm_mon];
1264 days += t->tm_mday - 1;
1266 secs = days * 86400 + t->tm_hour * 3600 + t->tm_min * 60 + t->tm_sec;
1267 return (time_t) secs;
1269 #endif /* HAVE_TIMEGM */
1272 /* strtoll is required by C99 and used by Wget only on systems with
1273 LFS. Unfortunately, some systems have LFS, but no strtoll or
1274 equivalent. These include HPUX 11.0 and Windows.
1276 We use #ifdef NEED_STRTOLL instead of #ifndef HAVE_STRTOLL because
1277 of the systems which have a suitable replacement (e.g. _strtoi64 on
1278 Windows), on which Wget's str_to_wgint is instructed to use that
1282 char_value (char c, int base)
1287 if ('0' <= c && c <= '9')
1289 else if ('a' <= c && c <= 'z')
1290 value = c - 'a' + 10;
1291 else if ('A' <= c && c <= 'Z')
1292 value = c - 'A' + 10;
1300 #define LL strtoll_type /* long long or __int64 */
1302 /* These constants assume 64-bit strtoll_type. */
1304 /* A roundabout way of writing 2**63-1 = 9223372036854775807 */
1305 #define STRTOLL_OVERFLOW (((LL) 1 << 62) - 1 + ((LL) 1 << 62))
1306 /* A roundabout way of writing -2**63 = -9223372036854775808 */
1307 #define STRTOLL_UNDERFLOW (-STRTOLL_OVERFLOW - 1)
1309 /* A strtoll replacement for systems that have LFS but don't supply
1310 strtoll. The headers typedef strtoll_type to long long or to
1314 strtoll (const char *nptr, char **endptr, int base)
1316 strtoll_type result = 0;
1319 if (base != 0 && (base < 2 || base > 36))
1325 while (*nptr == ' ' || *nptr == '\t')
1332 else if (*nptr == '+')
1340 /* If base is 0, determine the real base based on the beginning on
1341 the number; octal numbers begin with "0", hexadecimal with "0x",
1342 and the others are considered octal. */
1345 if ((base == 0 || base == 16)
1347 (*(nptr + 1) == 'x' || *(nptr + 1) == 'X'))
1360 /* Parse positive number, checking for overflow. */
1362 for (; (val = char_value (*nptr, base)) != -1; ++nptr)
1364 strtoll_type newresult = base * result + val;
1365 if (newresult < result)
1367 result = STRTOLL_OVERFLOW;
1376 /* Parse negative number, checking for underflow. */
1378 for (; (val = char_value (*nptr, base)) != -1; ++nptr)
1380 strtoll_type newresult = base * result - val;
1381 if (newresult > result)
1383 result = STRTOLL_UNDERFLOW;
1391 *endptr = (char *) nptr;
1394 #endif /* NEED_STRTOLL */