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