]> sjero.net Git - wget/blob - src/cmpt.c
NEWS: cite --start-pos
[wget] / src / cmpt.c
1 /* Replacements for routines missing on some systems.
2    Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
3    2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
4    Foundation, Inc.
5
6 This file is part of GNU Wget.
7
8 GNU Wget is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
12
13 GNU Wget is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with Wget.  If not, see <http://www.gnu.org/licenses/>.
20
21 Additional permission under GNU GPL version 3 section 7
22
23 If you modify this program, or any covered work, by linking or
24 combining it with the OpenSSL project's OpenSSL library (or a
25 modified version of that library), containing parts covered by the
26 terms of the OpenSSL or SSLeay licenses, the Free Software Foundation
27 grants you additional permission to convey the resulting work.
28 Corresponding Source for a non-source form of such a combination
29 shall include the source code for the parts of OpenSSL used as well
30 as that of the covered work.  */
31
32 #include "wget.h"
33
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <time.h>
38
39 #include <unistd.h>
40
41 #include <errno.h>
42
43 /* Some systems lack certain functions normally taken for granted.
44    For example, Windows doesn't have strptime, and some systems don't
45    have a usable fnmatch.  This file should contain fallback
46    implementations of such missing functions.  It should *not* define
47    new Wget-specific interfaces -- those should be placed in utils.c
48    or elsewhere.  */
49 \f
50 /* strcasecmp and strncasecmp apparently originated with BSD 4.4.
51    SUSv3 seems to be the only standard out there (that I can find)
52    that requires their existence, so in theory there might be systems
53    still in use that lack them.  Note that these don't get defined
54    under Windows because mswindows.h defines them to the equivalent
55    Windows functions stricmp and strnicmp.  */
56
57 #ifndef HAVE_STRCASECMP
58 /* From GNU libc.  */
59 /* Compare S1 and S2, ignoring case, returning less than, equal to or
60    greater than zero if S1 is lexiographically less than,
61    equal to or greater than S2.  */
62 int
63 strcasecmp (const char *s1, const char *s2)
64 {
65   register const unsigned char *p1 = (const unsigned char *) s1;
66   register const unsigned char *p2 = (const unsigned char *) s2;
67   unsigned char c1, c2;
68
69   if (p1 == p2)
70     return 0;
71
72   do
73     {
74       c1 = c_tolower (*p1++);
75       c2 = c_tolower (*p2++);
76       if (c1 == '\0')
77         break;
78     }
79   while (c1 == c2);
80
81   return c1 - c2;
82 }
83 #endif /* not HAVE_STRCASECMP */
84
85 #ifndef HAVE_STRNCASECMP
86 /* From GNU libc.  */
87 /* Compare no more than N characters of S1 and S2,
88    ignoring case, returning less than, equal to or
89    greater than zero if S1 is lexicographically less
90    than, equal to or greater than S2.  */
91 int
92 strncasecmp (const char *s1, const char *s2, size_t n)
93 {
94   register const unsigned char *p1 = (const unsigned char *) s1;
95   register const unsigned char *p2 = (const unsigned char *) s2;
96   unsigned char c1, c2;
97
98   if (p1 == p2 || n == 0)
99     return 0;
100
101   do
102     {
103       c1 = c_tolower (*p1++);
104       c2 = c_tolower (*p2++);
105       if (c1 == '\0' || c1 != c2)
106         return c1 - c2;
107     } while (--n > 0);
108
109   return c1 - c2;
110 }
111 #endif /* not HAVE_STRNCASECMP */
112
113 #ifndef HAVE_MEMRCHR
114 /* memrchr is a GNU extension.  It is like the memchr function, except
115    that it searches backwards from the end of the n bytes pointed to
116    by s instead of forwards from the front.  */
117
118 void *
119 memrchr (const void *s, int c, size_t n)
120 {
121   const char *b = s;
122   const char *e = b + n;
123   while (e > b)
124     if (*--e == c)
125       return (void *) e;
126   return NULL;
127 }
128 #endif
129 \f
130 /* strptime is required by POSIX, but it is missing from Windows,
131    which means we must keep a fallback implementation.  It is
132    reportedly missing or broken on many older Unix systems as well, so
133    it's good to have around.  */
134
135 #ifndef HAVE_STRPTIME
136 /* From GNU libc 2.1.3.  */
137 /* Ulrich, thanks for helping me out with this!  --hniksic  */
138
139 /* strptime - Convert a string representation of time to a time value.
140    Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
141    This file is part of the GNU C Library.
142    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.  */
143
144 /* XXX This version of the implementation is not really complete.
145    Some of the fields cannot add information alone.  But if seeing
146    some of them in the same format (such as year, week and weekday)
147    this is enough information for determining the date.  */
148
149 #ifndef __P
150 # define __P(args) args
151 #endif /* not __P */
152
153 #if ! HAVE_LOCALTIME_R && ! defined localtime_r
154 # ifdef _LIBC
155 #  define localtime_r __localtime_r
156 # else
157 /* Approximate localtime_r as best we can in its absence.  */
158 #  define localtime_r my_localtime_r
159 static struct tm *localtime_r __P ((const time_t *, struct tm *));
160 static struct tm *
161 localtime_r (t, tp)
162      const time_t *t;
163      struct tm *tp;
164 {
165   struct tm *l = localtime (t);
166   if (! l)
167     return 0;
168   *tp = *l;
169   return tp;
170 }
171 # endif /* ! _LIBC */
172 #endif /* ! HAVE_LOCALTIME_R && ! defined (localtime_r) */
173
174
175 #define match_char(ch1, ch2) if (ch1 != ch2) return NULL
176 #if defined __GNUC__ && __GNUC__ >= 2
177 # define match_string(cs1, s2) \
178   ({ size_t len = strlen (cs1);                                               \
179      int result = strncasecmp ((cs1), (s2), len) == 0;                        \
180      if (result) (s2) += len;                                                 \
181      result; })
182 #else
183 /* Oh come on.  Get a reasonable compiler.  */
184 # define match_string(cs1, s2) \
185   (strncasecmp ((cs1), (s2), strlen (cs1)) ? 0 : ((s2) += strlen (cs1), 1))
186 #endif
187 /* We intentionally do not use isdigit() for testing because this will
188    lead to problems with the wide character version.  */
189 #define get_number(from, to, n) \
190   do {                                                                        \
191     int __n = n;                                                              \
192     val = 0;                                                                  \
193     while (*rp == ' ')                                                        \
194       ++rp;                                                                   \
195     if (*rp < '0' || *rp > '9')                                               \
196       return NULL;                                                            \
197     do {                                                                      \
198       val *= 10;                                                              \
199       val += *rp++ - '0';                                                     \
200     } while (--__n > 0 && val * 10 <= to && *rp >= '0' && *rp <= '9');        \
201     if (val < from || val > to)                                               \
202       return NULL;                                                            \
203   } while (0)
204 #ifdef _NL_CURRENT
205 /* Added check for __GNUC__ extensions here for Wget. --abbotti */
206 # if defined __GNUC__ && __GNUC__ >= 2
207 #  define get_alt_number(from, to, n) \
208   ({                                                                          \
209     __label__ do_normal;                                                      \
210     if (*decided != raw)                                                      \
211       {                                                                       \
212         const char *alts = _NL_CURRENT (LC_TIME, ALT_DIGITS);                 \
213         int __n = n;                                                          \
214         int any = 0;                                                          \
215         while (*rp == ' ')                                                    \
216           ++rp;                                                               \
217         val = 0;                                                              \
218         do {                                                                  \
219           val *= 10;                                                          \
220           while (*alts != '\0')                                               \
221             {                                                                 \
222               size_t len = strlen (alts);                                     \
223               if (strncasecmp (alts, rp, len) == 0)                           \
224                 break;                                                        \
225               alts += len + 1;                                                \
226               ++val;                                                          \
227             }                                                                 \
228           if (*alts == '\0')                                                  \
229             {                                                                 \
230               if (*decided == not && ! any)                                   \
231                 goto do_normal;                                               \
232               /* If we haven't read anything it's an error.  */               \
233               if (! any)                                                      \
234                 return NULL;                                                  \
235               /* Correct the premature multiplication.  */                    \
236               val /= 10;                                                      \
237               break;                                                          \
238             }                                                                 \
239           else                                                                \
240             *decided = loc;                                                   \
241         } while (--__n > 0 && val * 10 <= to);                                \
242         if (val < from || val > to)                                           \
243           return NULL;                                                        \
244       }                                                                       \
245     else                                                                      \
246       {                                                                       \
247        do_normal:                                                             \
248         get_number (from, to, n);                                             \
249       }                                                                       \
250     0;                                                                        \
251   })
252 # else
253 #  define get_alt_number(from, to, n) \
254   do {
255     if (*decided != raw)                                                      \
256       {                                                                       \
257         const char *alts = _NL_CURRENT (LC_TIME, ALT_DIGITS);                 \
258         int __n = n;                                                          \
259         int any = 0;                                                          \
260         while (*rp == ' ')                                                    \
261           ++rp;                                                               \
262         val = 0;                                                              \
263         do {                                                                  \
264           val *= 10;                                                          \
265           while (*alts != '\0')                                               \
266             {                                                                 \
267               size_t len = strlen (alts);                                     \
268               if (strncasecmp (alts, rp, len) == 0)                           \
269                 break;                                                        \
270               alts += len + 1;                                                \
271               ++val;                                                          \
272             }                                                                 \
273           if (*alts == '\0')                                                  \
274             {                                                                 \
275               if (*decided == not && ! any)                                   \
276                 goto do_normal;                                               \
277               /* If we haven't read anything it's an error.  */               \
278               if (! any)                                                      \
279                 return NULL;                                                  \
280               /* Correct the premature multiplication.  */                    \
281               val /= 10;                                                      \
282               break;                                                          \
283             }                                                                 \
284           else                                                                \
285             *decided = loc;                                                   \
286         } while (--__n > 0 && val * 10 <= to);                                \
287         if (val < from || val > to)                                           \
288           return NULL;                                                        \
289       }                                                                       \
290     else                                                                      \
291       {                                                                       \
292        do_normal:                                                             \
293         get_number (from, to, n);                                             \
294       }                                                                       \
295   } while (0)
296 # endif /* defined __GNUC__ && __GNUC__ >= 2 */
297 #else
298 # define get_alt_number(from, to, n) \
299   /* We don't have the alternate representation.  */                          \
300   get_number(from, to, n)
301 #endif
302 #define recursive(new_fmt) \
303   (*(new_fmt) != '\0'                                                         \
304    && (rp = strptime_internal (rp, (new_fmt), tm, decided)) != NULL)
305
306
307 #ifdef _LIBC
308 /* This is defined in locale/C-time.c in the GNU libc.  */
309 extern const struct locale_data _nl_C_LC_TIME;
310 extern const unsigned short int __mon_yday[2][13];
311
312 # define weekday_name (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (DAY_1)].string)
313 # define ab_weekday_name \
314   (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (ABDAY_1)].string)
315 # define month_name (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (MON_1)].string)
316 # define ab_month_name (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (ABMON_1)].string)
317 # define HERE_D_T_FMT (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (D_T_FMT)].string)
318 # define HERE_D_FMT (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (D_FMT)].string)
319 # define HERE_AM_STR (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (AM_STR)].string)
320 # define HERE_PM_STR (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (PM_STR)].string)
321 # define HERE_T_FMT_AMPM \
322   (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (T_FMT_AMPM)].string)
323 # define HERE_T_FMT (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (T_FMT)].string)
324
325 # define strncasecmp(s1, s2, n) __strncasecmp (s1, s2, n)
326 #else
327 static char const weekday_name[][10] =
328   {
329     "Sunday", "Monday", "Tuesday", "Wednesday",
330     "Thursday", "Friday", "Saturday"
331   };
332 static char const ab_weekday_name[][4] =
333   {
334     "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
335   };
336 static char const month_name[][10] =
337   {
338     "January", "February", "March", "April", "May", "June",
339     "July", "August", "September", "October", "November", "December"
340   };
341 static char const ab_month_name[][4] =
342   {
343     "Jan", "Feb", "Mar", "Apr", "May", "Jun",
344     "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
345   };
346 # define HERE_D_T_FMT "%a %b %e %H:%M:%S %Y"
347 # define HERE_D_FMT "%m/%d/%y"
348 # define HERE_AM_STR "AM"
349 # define HERE_PM_STR "PM"
350 # define HERE_T_FMT_AMPM "%I:%M:%S %p"
351 # define HERE_T_FMT "%H:%M:%S"
352
353 const unsigned short int __mon_yday[2][13];
354 # ifndef NEED_MON_YDAY
355 #  define NEED_MON_YDAY
356 # endif
357 #endif
358
359 /* Status of lookup: do we use the locale data or the raw data?  */
360 enum locale_status { not, loc, raw };
361
362
363 #ifndef __isleap
364 /* Nonzero if YEAR is a leap year (every 4 years,
365    except every 100th isn't, and every 400th is).  */
366 # define __isleap(year) \
367   ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
368 #endif
369
370 /* Compute the day of the week.  */
371 static void
372 day_of_the_week (struct tm *tm)
373 {
374   /* We know that January 1st 1970 was a Thursday (= 4).  Compute the
375      the difference between this data in the one on TM and so determine
376      the weekday.  */
377   int corr_year = 1900 + tm->tm_year - (tm->tm_mon < 2);
378   int wday = (-473
379               + (365 * (tm->tm_year - 70))
380               + (corr_year / 4)
381               - ((corr_year / 4) / 25) + ((corr_year / 4) % 25 < 0)
382               + (((corr_year / 4) / 25) / 4)
383               + __mon_yday[0][tm->tm_mon]
384               + tm->tm_mday - 1);
385   tm->tm_wday = ((wday % 7) + 7) % 7;
386 }
387
388 /* Compute the day of the year.  */
389 static void
390 day_of_the_year (struct tm *tm)
391 {
392   tm->tm_yday = (__mon_yday[__isleap (1900 + tm->tm_year)][tm->tm_mon]
393                  + (tm->tm_mday - 1));
394 }
395
396 static char *
397 #ifdef _LIBC
398 internal_function
399 #endif
400 strptime_internal __P ((const char *buf, const char *format, struct tm *tm,
401                         enum locale_status *decided));
402
403 static char *
404 #ifdef _LIBC
405 internal_function
406 #endif
407 strptime_internal (rp, fmt, tm, decided)
408      const char *rp;
409      const char *fmt;
410      struct tm *tm;
411      enum locale_status *decided;
412 {
413 #ifdef _NL_CURRENT
414   const char *rp_backup;
415 #endif
416   int cnt;
417   size_t val;
418   int have_I, is_pm;
419   int century, want_century;
420   int have_wday, want_xday;
421   int have_yday;
422   int have_mon, have_mday;
423
424   have_I = is_pm = 0;
425   century = -1;
426   want_century = 0;
427   have_wday = want_xday = have_yday = have_mon = have_mday = 0;
428
429   while (*fmt != '\0')
430     {
431       /* A white space in the format string matches 0 more or white
432          space in the input string.  */
433       if (c_isspace (*fmt))
434         {
435           while (c_isspace (*rp))
436             ++rp;
437           ++fmt;
438           continue;
439         }
440
441       /* Any character but `%' must be matched by the same character
442          in the iput string.  */
443       if (*fmt != '%')
444         {
445           match_char (*fmt++, *rp++);
446           continue;
447         }
448
449       ++fmt;
450 #ifndef _NL_CURRENT
451       /* We need this for handling the `E' modifier.  */
452     start_over:
453 #endif
454
455 #ifdef _NL_CURRENT
456       /* Make back up of current processing pointer.  */
457       rp_backup = rp;
458 #endif
459
460       switch (*fmt++)
461         {
462         case '%':
463           /* Match the `%' character itself.  */
464           match_char ('%', *rp++);
465           break;
466         case 'a':
467         case 'A':
468           /* Match day of week.  */
469           for (cnt = 0; cnt < 7; ++cnt)
470             {
471 #ifdef _NL_CURRENT
472               if (*decided !=raw)
473                 {
474                   if (match_string (_NL_CURRENT (LC_TIME, DAY_1 + cnt), rp))
475                     {
476                       if (*decided == not
477                           && strcmp (_NL_CURRENT (LC_TIME, DAY_1 + cnt),
478                                      weekday_name[cnt]))
479                         *decided = loc;
480                       break;
481                     }
482                   if (match_string (_NL_CURRENT (LC_TIME, ABDAY_1 + cnt), rp))
483                     {
484                       if (*decided == not
485                           && strcmp (_NL_CURRENT (LC_TIME, ABDAY_1 + cnt),
486                                      ab_weekday_name[cnt]))
487                         *decided = loc;
488                       break;
489                     }
490                 }
491 #endif
492               if (*decided != loc
493                   && (match_string (weekday_name[cnt], rp)
494                       || match_string (ab_weekday_name[cnt], rp)))
495                 {
496                   *decided = raw;
497                   break;
498                 }
499             }
500           if (cnt == 7)
501             /* Does not match a weekday name.  */
502             return NULL;
503           tm->tm_wday = cnt;
504           have_wday = 1;
505           break;
506         case 'b':
507         case 'B':
508         case 'h':
509           /* Match month name.  */
510           for (cnt = 0; cnt < 12; ++cnt)
511             {
512 #ifdef _NL_CURRENT
513               if (*decided !=raw)
514                 {
515                   if (match_string (_NL_CURRENT (LC_TIME, MON_1 + cnt), rp))
516                     {
517                       if (*decided == not
518                           && strcmp (_NL_CURRENT (LC_TIME, MON_1 + cnt),
519                                      month_name[cnt]))
520                         *decided = loc;
521                       break;
522                     }
523                   if (match_string (_NL_CURRENT (LC_TIME, ABMON_1 + cnt), rp))
524                     {
525                       if (*decided == not
526                           && strcmp (_NL_CURRENT (LC_TIME, ABMON_1 + cnt),
527                                      ab_month_name[cnt]))
528                         *decided = loc;
529                       break;
530                     }
531                 }
532 #endif
533               if (match_string (month_name[cnt], rp)
534                   || match_string (ab_month_name[cnt], rp))
535                 {
536                   *decided = raw;
537                   break;
538                 }
539             }
540           if (cnt == 12)
541             /* Does not match a month name.  */
542             return NULL;
543           tm->tm_mon = cnt;
544           want_xday = 1;
545           break;
546         case 'c':
547           /* Match locale's date and time format.  */
548 #ifdef _NL_CURRENT
549           if (*decided != raw)
550             {
551               if (!recursive (_NL_CURRENT (LC_TIME, D_T_FMT)))
552                 {
553                   if (*decided == loc)
554                     return NULL;
555                   else
556                     rp = rp_backup;
557                 }
558               else
559                 {
560                   if (*decided == not &&
561                       strcmp (_NL_CURRENT (LC_TIME, D_T_FMT), HERE_D_T_FMT))
562                     *decided = loc;
563                   want_xday = 1;
564                   break;
565                 }
566               *decided = raw;
567             }
568 #endif
569           if (!recursive (HERE_D_T_FMT))
570             return NULL;
571           want_xday = 1;
572           break;
573         case 'C':
574           /* Match century number.  */
575           get_number (0, 99, 2);
576           century = val;
577           want_xday = 1;
578           break;
579         case 'd':
580         case 'e':
581           /* Match day of month.  */
582           get_number (1, 31, 2);
583           tm->tm_mday = val;
584           have_mday = 1;
585           want_xday = 1;
586           break;
587         case 'F':
588           if (!recursive ("%Y-%m-%d"))
589             return NULL;
590           want_xday = 1;
591           break;
592         case 'x':
593 #ifdef _NL_CURRENT
594           if (*decided != raw)
595             {
596               if (!recursive (_NL_CURRENT (LC_TIME, D_FMT)))
597                 {
598                   if (*decided == loc)
599                     return NULL;
600                   else
601                     rp = rp_backup;
602                 }
603               else
604                 {
605                   if (*decided == not
606                       && strcmp (_NL_CURRENT (LC_TIME, D_FMT), HERE_D_FMT))
607                     *decided = loc;
608                   want_xday = 1;
609                   break;
610                 }
611               *decided = raw;
612             }
613 #endif
614           /* Fall through.  */
615         case 'D':
616           /* Match standard day format.  */
617           if (!recursive (HERE_D_FMT))
618             return NULL;
619           want_xday = 1;
620           break;
621         case 'k':
622         case 'H':
623           /* Match hour in 24-hour clock.  */
624           get_number (0, 23, 2);
625           tm->tm_hour = val;
626           have_I = 0;
627           break;
628         case 'I':
629           /* Match hour in 12-hour clock.  */
630           get_number (1, 12, 2);
631           tm->tm_hour = val % 12;
632           have_I = 1;
633           break;
634         case 'j':
635           /* Match day number of year.  */
636           get_number (1, 366, 3);
637           tm->tm_yday = val - 1;
638           have_yday = 1;
639           break;
640         case 'm':
641           /* Match number of month.  */
642           get_number (1, 12, 2);
643           tm->tm_mon = val - 1;
644           have_mon = 1;
645           want_xday = 1;
646           break;
647         case 'M':
648           /* Match minute.  */
649           get_number (0, 59, 2);
650           tm->tm_min = val;
651           break;
652         case 'n':
653         case 't':
654           /* Match any white space.  */
655           while (c_isspace (*rp))
656             ++rp;
657           break;
658         case 'p':
659           /* Match locale's equivalent of AM/PM.  */
660 #ifdef _NL_CURRENT
661           if (*decided != raw)
662             {
663               if (match_string (_NL_CURRENT (LC_TIME, AM_STR), rp))
664                 {
665                   if (strcmp (_NL_CURRENT (LC_TIME, AM_STR), HERE_AM_STR))
666                     *decided = loc;
667                   break;
668                 }
669               if (match_string (_NL_CURRENT (LC_TIME, PM_STR), rp))
670                 {
671                   if (strcmp (_NL_CURRENT (LC_TIME, PM_STR), HERE_PM_STR))
672                     *decided = loc;
673                   is_pm = 1;
674                   break;
675                 }
676               *decided = raw;
677             }
678 #endif
679           if (!match_string (HERE_AM_STR, rp))
680             {
681               if (match_string (HERE_PM_STR, rp))
682                 is_pm = 1;
683               else
684                 return NULL;
685             }
686           break;
687         case 'r':
688 #ifdef _NL_CURRENT
689           if (*decided != raw)
690             {
691               if (!recursive (_NL_CURRENT (LC_TIME, T_FMT_AMPM)))
692                 {
693                   if (*decided == loc)
694                     return NULL;
695                   else
696                     rp = rp_backup;
697                 }
698               else
699                 {
700                   if (*decided == not &&
701                       strcmp (_NL_CURRENT (LC_TIME, T_FMT_AMPM),
702                               HERE_T_FMT_AMPM))
703                     *decided = loc;
704                   break;
705                 }
706               *decided = raw;
707             }
708 #endif
709           if (!recursive (HERE_T_FMT_AMPM))
710             return NULL;
711           break;
712         case 'R':
713           if (!recursive ("%H:%M"))
714             return NULL;
715           break;
716         case 's':
717           {
718             /* The number of seconds may be very high so we cannot use
719                the `get_number' macro.  Instead read the number
720                character for character and construct the result while
721                doing this.  */
722             time_t secs = 0;
723             if (*rp < '0' || *rp > '9')
724               /* We need at least one digit.  */
725               return NULL;
726
727             do
728               {
729                 secs *= 10;
730                 secs += *rp++ - '0';
731               }
732             while (*rp >= '0' && *rp <= '9');
733
734             if (localtime_r (&secs, tm) == NULL)
735               /* Error in function.  */
736               return NULL;
737           }
738           break;
739         case 'S':
740           get_number (0, 61, 2);
741           tm->tm_sec = val;
742           break;
743         case 'X':
744 #ifdef _NL_CURRENT
745           if (*decided != raw)
746             {
747               if (!recursive (_NL_CURRENT (LC_TIME, T_FMT)))
748                 {
749                   if (*decided == loc)
750                     return NULL;
751                   else
752                     rp = rp_backup;
753                 }
754               else
755                 {
756                   if (strcmp (_NL_CURRENT (LC_TIME, T_FMT), HERE_T_FMT))
757                     *decided = loc;
758                   break;
759                 }
760               *decided = raw;
761             }
762 #endif
763           /* Fall through.  */
764         case 'T':
765           if (!recursive (HERE_T_FMT))
766             return NULL;
767           break;
768         case 'u':
769           get_number (1, 7, 1);
770           tm->tm_wday = val % 7;
771           have_wday = 1;
772           break;
773         case 'g':
774           get_number (0, 99, 2);
775           /* XXX This cannot determine any field in TM.  */
776           break;
777         case 'G':
778           if (*rp < '0' || *rp > '9')
779             return NULL;
780           /* XXX Ignore the number since we would need some more
781              information to compute a real date.  */
782           do
783             ++rp;
784           while (*rp >= '0' && *rp <= '9');
785           break;
786         case 'U':
787         case 'V':
788         case 'W':
789           get_number (0, 53, 2);
790           /* XXX This cannot determine any field in TM without some
791              information.  */
792           break;
793         case 'w':
794           /* Match number of weekday.  */
795           get_number (0, 6, 1);
796           tm->tm_wday = val;
797           have_wday = 1;
798           break;
799         case 'y':
800           /* Match year within century.  */
801           get_number (0, 99, 2);
802           /* The "Year 2000: The Millennium Rollover" paper suggests that
803              values in the range 69-99 refer to the twentieth century.  */
804           tm->tm_year = val >= 69 ? val : val + 100;
805           /* Indicate that we want to use the century, if specified.  */
806           want_century = 1;
807           want_xday = 1;
808           break;
809         case 'Y':
810           /* Match year including century number.  */
811           get_number (0, 9999, 4);
812           tm->tm_year = val - 1900;
813           want_century = 0;
814           want_xday = 1;
815           break;
816         case 'Z':
817           /* XXX How to handle this?  */
818           break;
819         case 'E':
820 #ifdef _NL_CURRENT
821           switch (*fmt++)
822             {
823             case 'c':
824               /* Match locale's alternate date and time format.  */
825               if (*decided != raw)
826                 {
827                   const char *fmt = _NL_CURRENT (LC_TIME, ERA_D_T_FMT);
828
829                   if (*fmt == '\0')
830                     fmt = _NL_CURRENT (LC_TIME, D_T_FMT);
831
832                   if (!recursive (fmt))
833                     {
834                       if (*decided == loc)
835                         return NULL;
836                       else
837                         rp = rp_backup;
838                     }
839                   else
840                     {
841                       if (strcmp (fmt, HERE_D_T_FMT))
842                         *decided = loc;
843                       want_xday = 1;
844                       break;
845                     }
846                   *decided = raw;
847                 }
848               /* The C locale has no era information, so use the
849                  normal representation.  */
850               if (!recursive (HERE_D_T_FMT))
851                 return NULL;
852               want_xday = 1;
853               break;
854             case 'C':
855             case 'y':
856             case 'Y':
857               /* Match name of base year in locale's alternate
858                  representation.  */
859               /* XXX This is currently not implemented.  It should
860                  use the value _NL_CURRENT (LC_TIME, ERA).  */
861               break;
862             case 'x':
863               if (*decided != raw)
864                 {
865                   const char *fmt = _NL_CURRENT (LC_TIME, ERA_D_FMT);
866
867                   if (*fmt == '\0')
868                     fmt = _NL_CURRENT (LC_TIME, D_FMT);
869
870                   if (!recursive (fmt))
871                     {
872                       if (*decided == loc)
873                         return NULL;
874                       else
875                         rp = rp_backup;
876                     }
877                   else
878                     {
879                       if (strcmp (fmt, HERE_D_FMT))
880                         *decided = loc;
881                       break;
882                     }
883                   *decided = raw;
884                 }
885               if (!recursive (HERE_D_FMT))
886                 return NULL;
887               break;
888             case 'X':
889               if (*decided != raw)
890                 {
891                   const char *fmt = _NL_CURRENT (LC_TIME, ERA_T_FMT);
892
893                   if (*fmt == '\0')
894                     fmt = _NL_CURRENT (LC_TIME, T_FMT);
895
896                   if (!recursive (fmt))
897                     {
898                       if (*decided == loc)
899                         return NULL;
900                       else
901                         rp = rp_backup;
902                     }
903                   else
904                     {
905                       if (strcmp (fmt, HERE_T_FMT))
906                         *decided = loc;
907                       break;
908                     }
909                   *decided = raw;
910                 }
911               if (!recursive (HERE_T_FMT))
912                 return NULL;
913               break;
914             default:
915               return NULL;
916             }
917           break;
918 #else
919           /* We have no information about the era format.  Just use
920              the normal format.  */
921           if (*fmt != 'c' && *fmt != 'C' && *fmt != 'y' && *fmt != 'Y'
922               && *fmt != 'x' && *fmt != 'X')
923             /* This is an illegal format.  */
924             return NULL;
925
926           goto start_over;
927 #endif
928         case 'O':
929           switch (*fmt++)
930             {
931             case 'd':
932             case 'e':
933               /* Match day of month using alternate numeric symbols.  */
934               get_alt_number (1, 31, 2);
935               tm->tm_mday = val;
936               have_mday = 1;
937               want_xday = 1;
938               break;
939             case 'H':
940               /* Match hour in 24-hour clock using alternate numeric
941                  symbols.  */
942               get_alt_number (0, 23, 2);
943               tm->tm_hour = val;
944               have_I = 0;
945               break;
946             case 'I':
947               /* Match hour in 12-hour clock using alternate numeric
948                  symbols.  */
949               get_alt_number (1, 12, 2);
950               tm->tm_hour = val - 1;
951               have_I = 1;
952               break;
953             case 'm':
954               /* Match month using alternate numeric symbols.  */
955               get_alt_number (1, 12, 2);
956               tm->tm_mon = val - 1;
957               have_mon = 1;
958               want_xday = 1;
959               break;
960             case 'M':
961               /* Match minutes using alternate numeric symbols.  */
962               get_alt_number (0, 59, 2);
963               tm->tm_min = val;
964               break;
965             case 'S':
966               /* Match seconds using alternate numeric symbols.  */
967               get_alt_number (0, 61, 2);
968               tm->tm_sec = val;
969               break;
970             case 'U':
971             case 'V':
972             case 'W':
973               get_alt_number (0, 53, 2);
974               /* XXX This cannot determine any field in TM without
975                  further information.  */
976               break;
977             case 'w':
978               /* Match number of weekday using alternate numeric symbols.  */
979               get_alt_number (0, 6, 1);
980               tm->tm_wday = val;
981               have_wday = 1;
982               break;
983             case 'y':
984               /* Match year within century using alternate numeric symbols.  */
985               get_alt_number (0, 99, 2);
986               tm->tm_year = val >= 69 ? val : val + 100;
987               want_xday = 1;
988               break;
989             default:
990               return NULL;
991             }
992           break;
993         default:
994           return NULL;
995         }
996     }
997
998   if (have_I && is_pm)
999     tm->tm_hour += 12;
1000
1001   if (century != -1)
1002     {
1003       if (want_century)
1004         tm->tm_year = tm->tm_year % 100 + (century - 19) * 100;
1005       else
1006         /* Only the century, but not the year.  Strange, but so be it.  */
1007         tm->tm_year = (century - 19) * 100;
1008     }
1009
1010   if (want_xday && !have_wday) {
1011       if ( !(have_mon && have_mday) && have_yday)  {
1012           /* we don't have tm_mon and/or tm_mday, compute them */
1013           int t_mon = 0;
1014           while (__mon_yday[__isleap(1900 + tm->tm_year)][t_mon] <= tm->tm_yday)
1015               t_mon++;
1016           if (!have_mon)
1017               tm->tm_mon = t_mon - 1;
1018           if (!have_mday)
1019               tm->tm_mday = tm->tm_yday - __mon_yday[__isleap(1900 + tm->tm_year)][t_mon - 1] + 1;
1020       }
1021       day_of_the_week (tm);
1022   }
1023   if (want_xday && !have_yday)
1024     day_of_the_year (tm);
1025
1026   return (char *) rp;
1027 }
1028
1029
1030 char *
1031 strptime (buf, format, tm)
1032      const char *buf;
1033      const char *format;
1034      struct tm *tm;
1035 {
1036   enum locale_status decided;
1037 #ifdef _NL_CURRENT
1038   decided = not;
1039 #else
1040   decided = raw;
1041 #endif
1042   return strptime_internal (buf, format, tm, &decided);
1043 }
1044 #endif /* not HAVE_STRPTIME */
1045
1046 #ifdef NEED_MON_YDAY
1047 const unsigned short int __mon_yday[2][13] =
1048   {
1049     /* Normal years.  */
1050     { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
1051     /* Leap years.  */
1052     { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
1053   };
1054 #endif
1055 \f
1056 /* fnmatch is required by POSIX, but we include an implementation for
1057    the sake of systems that don't have it, most notably Windows.  Some
1058    systems do have fnmatch, but Apache's installation process installs
1059    its own fnmatch.h (incompatible with the system one!) in a system
1060    include directory, effectively rendering fnmatch unusable.  This
1061    has been fixed with Apache 2, where fnmatch has been moved to apr
1062    and given a prefix, but many systems out there are still (as of
1063    this writing in 2005) broken and we must cater to them.
1064
1065    Additionally, according to some conventional wisdom, many
1066    historical implementations of fnmatch are buggy and unreliable.  If
1067    yours is such, undefine SYSTEM_FNMATCH in sysdep.h and tell us
1068    about it.  */
1069
1070 #ifndef SYSTEM_FNMATCH
1071
1072 #define __FNM_FLAGS     (FNM_PATHNAME | FNM_NOESCAPE | FNM_PERIOD)
1073
1074 /* Match STRING against the filename pattern PATTERN, returning zero
1075    if it matches, FNM_NOMATCH if not.  This implementation comes from
1076    an earlier version of GNU Bash.  (It doesn't make sense to update
1077    it with a newer version because those versions add a lot of
1078    features Wget doesn't use or care about.)  */
1079
1080 int
1081 fnmatch (const char *pattern, const char *string, int flags)
1082 {
1083   register const char *p = pattern, *n = string;
1084   register char c;
1085
1086   if ((flags & ~__FNM_FLAGS) != 0)
1087     {
1088       errno = EINVAL;
1089       return (-1);
1090     }
1091
1092   while ((c = *p++) != '\0')
1093     {
1094       switch (c)
1095         {
1096         case '?':
1097           if (*n == '\0')
1098             return (FNM_NOMATCH);
1099           else if ((flags & FNM_PATHNAME) && *n == '/')
1100             return (FNM_NOMATCH);
1101           else if ((flags & FNM_PERIOD) && *n == '.' &&
1102                    (n == string || ((flags & FNM_PATHNAME) && n[-1] == '/')))
1103             return (FNM_NOMATCH);
1104           break;
1105
1106         case '\\':
1107           if (!(flags & FNM_NOESCAPE))
1108             c = *p++;
1109           if (*n != c)
1110             return (FNM_NOMATCH);
1111           break;
1112
1113         case '*':
1114           if ((flags & FNM_PERIOD) && *n == '.' &&
1115               (n == string || ((flags & FNM_PATHNAME) && n[-1] == '/')))
1116             return (FNM_NOMATCH);
1117
1118           for (c = *p++; c == '?' || c == '*'; c = *p++, ++n)
1119             if (((flags & FNM_PATHNAME) && *n == '/') ||
1120                 (c == '?' && *n == '\0'))
1121               return (FNM_NOMATCH);
1122
1123           if (c == '\0')
1124             return (0);
1125
1126           {
1127             char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c;
1128             for (--p; *n != '\0'; ++n)
1129               if ((c == '[' || *n == c1) &&
1130                   fnmatch (p, n, flags & ~FNM_PERIOD) == 0)
1131                 return (0);
1132             return (FNM_NOMATCH);
1133           }
1134
1135         case '[':
1136           {
1137             /* Nonzero if the sense of the character class is
1138                inverted.  */
1139             register int not;
1140
1141             if (*n == '\0')
1142               return (FNM_NOMATCH);
1143
1144             if ((flags & FNM_PERIOD) && *n == '.' &&
1145                 (n == string || ((flags & FNM_PATHNAME) && n[-1] == '/')))
1146               return (FNM_NOMATCH);
1147
1148             /* Make sure there is a closing `]'.  If there isn't,
1149                the `[' is just a character to be matched.  */
1150             {
1151               register const char *np;
1152
1153               for (np = p; np && *np && *np != ']'; np++)
1154                 ;
1155
1156               if (np && !*np)
1157                 {
1158                   if (*n != '[')
1159                     return (FNM_NOMATCH);
1160                   goto next_char;
1161                 }
1162             }
1163
1164             not = (*p == '!' || *p == '^');
1165             if (not)
1166               ++p;
1167
1168             c = *p++;
1169             while (1)
1170               {
1171                 register char cstart = c, cend = c;
1172
1173                 if (!(flags & FNM_NOESCAPE) && c == '\\')
1174                   cstart = cend = *p++;
1175
1176                 if (c == '\0')
1177                   /* [ (unterminated) loses.  */
1178                   return (FNM_NOMATCH);
1179
1180                 c = *p++;
1181
1182                 if ((flags & FNM_PATHNAME) && c == '/')
1183                   /* [/] can never match.  */
1184                   return (FNM_NOMATCH);
1185
1186                 if (c == '-' && *p != ']')
1187                   {
1188                     cend = *p++;
1189                     if (!(flags & FNM_NOESCAPE) && cend == '\\')
1190                       cend = *p++;
1191                     if (cend == '\0')
1192                       return (FNM_NOMATCH);
1193                     c = *p++;
1194                   }
1195
1196                 if (*n >= cstart && *n <= cend)
1197                   goto matched;
1198
1199                 if (c == ']')
1200                   break;
1201               }
1202             if (!not)
1203               return (FNM_NOMATCH);
1204
1205           next_char:
1206             break;
1207
1208           matched:
1209             /* Skip the rest of the [...] that already matched.  */
1210             while (c != ']')
1211               {
1212                 if (c == '\0')
1213                   /* [... (unterminated) loses.  */
1214                   return (FNM_NOMATCH);
1215
1216                 c = *p++;
1217                 if (!(flags & FNM_NOESCAPE) && c == '\\')
1218                   /* 1003.2d11 is unclear if this is right.  %%% */
1219                   ++p;
1220               }
1221             if (not)
1222               return (FNM_NOMATCH);
1223           }
1224           break;
1225
1226         default:
1227           if (c != *n)
1228             return (FNM_NOMATCH);
1229         }
1230
1231       ++n;
1232     }
1233
1234   if (*n == '\0')
1235     return (0);
1236
1237   return (FNM_NOMATCH);
1238 }
1239
1240 #endif /* not SYSTEM_FNMATCH */
1241 \f
1242 #ifndef HAVE_TIMEGM
1243 /* timegm is a GNU extension, but lately also available on *BSD
1244    systems and possibly elsewhere. */
1245
1246 /* True if YEAR is a leap year. */
1247 #define ISLEAP(year)                                            \
1248   ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
1249
1250 /* Number of leap years in the range [y1, y2). */
1251 #define LEAPYEARS(y1, y2)                                               \
1252   ((y2-1)/4 - (y1-1)/4) - ((y2-1)/100 - (y1-1)/100) + ((y2-1)/400 - (y1-1)/400)
1253
1254 /* Inverse of gmtime: converts struct tm to time_t, assuming the data
1255    in tm is UTC rather than local timezone.  This implementation
1256    returns the number of seconds elapsed since midnight 1970-01-01,
1257    converted to time_t.  */
1258
1259 time_t
1260 timegm (struct tm *t)
1261 {
1262   static const unsigned short int month_to_days[][13] = {
1263     { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }, /* normal */
1264     { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 }  /* leap */
1265   };
1266   const int year = 1900 + t->tm_year;
1267   unsigned long secs;  /* until 2106-02-07 for 32-bit unsigned long */
1268   int days;
1269
1270   if (year < 1970)
1271     return (time_t) -1;
1272
1273   days = 365 * (year - 1970);
1274   /* Take into account leap years between 1970 and YEAR, not counting
1275      YEAR itself.  */
1276   days += LEAPYEARS (1970, year);
1277   if (t->tm_mon < 0 || t->tm_mon >= 12)
1278     return (time_t) -1;
1279   days += month_to_days[ISLEAP (year)][t->tm_mon];
1280   days += t->tm_mday - 1;
1281
1282   secs = days * 86400 + t->tm_hour * 3600 + t->tm_min * 60 + t->tm_sec;
1283   return (time_t) secs;
1284 }
1285 #endif /* HAVE_TIMEGM */
1286
1287 #ifdef NEED_STRTOLL
1288 /* strtoll is required by C99 and used by Wget only on systems with
1289    LFS.  Unfortunately, some systems have LFS, but no strtoll or
1290    equivalent.  These include HPUX 11.0 and Windows.
1291
1292    We use #ifdef NEED_STRTOLL instead of #ifndef HAVE_STRTOLL because
1293    of the systems which have a suitable replacement (e.g. _strtoi64 on
1294    Windows), on which Wget's str_to_wgint is instructed to use that
1295    instead.  */
1296
1297 static inline int
1298 char_value (char c, int base)
1299 {
1300   int value;
1301   if (c < '0')
1302     return -1;
1303   if ('0' <= c && c <= '9')
1304     value = c - '0';
1305   else if ('a' <= c && c <= 'z')
1306     value = c - 'a' + 10;
1307   else if ('A' <= c && c <= 'Z')
1308     value = c - 'A' + 10;
1309   else
1310     return -1;
1311   if (value >= base)
1312     return -1;
1313   return value;
1314 }
1315
1316 #define STRTOLL_MAX TYPE_MAXIMUM (strtoll_type)
1317 /* This definition assumes two's complement arithmetic */
1318 #define STRTOLL_MIN (-STRTOLL_MAX - 1)
1319
1320 /* Like a%b, but always returns a positive number when A is negative.
1321    (C doesn't guarantee the sign of the result.)  */
1322 #define MOD(a, b) ((strtoll_type) -1 % 2 == 1 ? (a) % (b) : - ((a) % (b)))
1323
1324 /* A strtoll-like replacement for systems that have an integral type
1325    larger than long but don't supply strtoll.  This implementation
1326    makes no assumptions about the size of strtoll_type.  */
1327
1328 strtoll_type
1329 strtoll (const char *nptr, char **endptr, int base)
1330 {
1331   strtoll_type result = 0;
1332   bool negative;
1333
1334   if (base != 0 && (base < 2 || base > 36))
1335     {
1336       errno = EINVAL;
1337       return 0;
1338     }
1339
1340   while (*nptr == ' ' || *nptr == '\t')
1341     ++nptr;
1342   if (*nptr == '-')
1343     {
1344       negative = true;
1345       ++nptr;
1346     }
1347   else if (*nptr == '+')
1348     {
1349       negative = false;
1350       ++nptr;
1351     }
1352   else
1353     negative = false;
1354
1355   /* If BASE is 0, determine the real base based on the beginning on
1356      the number; octal numbers begin with "0", hexadecimal with "0x",
1357      and the others are considered octal.  */
1358   if (*nptr == '0')
1359     {
1360       if ((base == 0 || base == 16)
1361           &&
1362           (*(nptr + 1) == 'x' || *(nptr + 1) == 'X'))
1363         {
1364           base = 16;
1365           nptr += 2;
1366           /* "0x" must be followed by at least one hex char.  If not,
1367              return 0 and place ENDPTR on 'x'. */
1368           if (!c_isxdigit (*nptr))
1369             {
1370               --nptr;
1371               goto out;
1372             }
1373         }
1374       else if (base == 0)
1375         base = 8;
1376     }
1377   else if (base == 0)
1378     base = 10;
1379
1380   if (!negative)
1381     {
1382       /* Parse positive number, checking for overflow. */
1383       int digit;
1384       /* Overflow watermark.  If RESULT exceeds it, overflow occurs on
1385          this digit.  If result==WATERMARK, current digit may not
1386          exceed the last digit of maximum value. */
1387       const strtoll_type WATERMARK = STRTOLL_MAX / base;
1388       for (; (digit = char_value (*nptr, base)) != -1; ++nptr)
1389         {
1390           if (result > WATERMARK
1391               || (result == WATERMARK && digit > STRTOLL_MAX % base))
1392             {
1393               result = STRTOLL_MAX;
1394               errno = ERANGE;
1395               break;
1396             }
1397           result = base * result + digit;
1398         }
1399     }
1400   else
1401     {
1402       /* Parse negative number, checking for underflow. */
1403       int digit;
1404       const strtoll_type WATERMARK = STRTOLL_MIN / base;
1405       for (; (digit = char_value (*nptr, base)) != -1; ++nptr)
1406         {
1407           if (result < WATERMARK
1408               || (result == WATERMARK && digit > MOD (STRTOLL_MIN, base)))
1409             {
1410               result = STRTOLL_MIN;
1411               errno = ERANGE;
1412               break;
1413             }
1414           result = base * result - digit;
1415         }
1416     }
1417  out:
1418   if (endptr)
1419     *endptr = (char *) nptr;
1420   return result;
1421 }
1422
1423 #undef STRTOLL_MAX
1424 #undef STRTOLL_MIN
1425 #undef ABS
1426
1427 #endif  /* NEED_STRTOLL */