]> sjero.net Git - wget/blob - src/cmpt.c
[svn] Update strstr to the one in glibc 2.3.5.
[wget] / src / cmpt.c
1 /* Replacements for routines missing on some systems.
2    Copyright (C) 1995-2005 Free Software Foundation, Inc.
3
4 This file is part of GNU Wget.
5
6 GNU Wget is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 GNU Wget is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with Wget; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
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 #ifdef HAVE_STRING_H
35 # include <string.h>
36 #else
37 # include <strings.h>
38 #endif /* HAVE_STRING_H */
39
40 #include <sys/types.h>
41 #ifdef HAVE_UNISTD_H
42 # include <unistd.h>
43 #endif
44 #include <limits.h>
45
46 #include <errno.h>
47 #ifndef errno
48 extern int errno;
49 #endif
50
51 #include "wget.h"
52
53 #ifndef HAVE_STRERROR
54 /* A strerror() clone, for systems that don't have it.  */
55 char *
56 strerror (int err)
57 {
58   /* This loses on a system without `sys_errlist'.  */
59   extern char *sys_errlist[];
60   return sys_errlist[err];
61 }
62 #endif /* not HAVE_STRERROR */
63
64 /* Some systems don't have some str* functions in libc.  Here we
65    define them.  The same goes for strptime.  */
66
67 #ifndef HAVE_STRCASECMP
68 /* From GNU libc.  */
69 /* Compare S1 and S2, ignoring case, returning less than, equal to or
70    greater than zero if S1 is lexiographically less than,
71    equal to or greater than S2.  */
72 int
73 strcasecmp (const char *s1, const char *s2)
74 {
75   register const unsigned char *p1 = (const unsigned char *) s1;
76   register const unsigned char *p2 = (const unsigned char *) s2;
77   unsigned char c1, c2;
78
79   if (p1 == p2)
80     return 0;
81
82   do
83     {
84       c1 = TOLOWER (*p1++);
85       c2 = TOLOWER (*p2++);
86       if (c1 == '\0')
87         break;
88     }
89   while (c1 == c2);
90
91   return c1 - c2;
92 }
93 #endif /* not HAVE_STRCASECMP */
94
95 #ifndef HAVE_STRNCASECMP
96 /* From GNU libc.  */
97 /* Compare no more than N characters of S1 and S2,
98    ignoring case, returning less than, equal to or
99    greater than zero if S1 is lexicographically less
100    than, equal to or greater than S2.  */
101 int
102 strncasecmp (const char *s1, const char *s2, size_t n)
103 {
104   register const unsigned char *p1 = (const unsigned char *) s1;
105   register const unsigned char *p2 = (const unsigned char *) s2;
106   unsigned char c1, c2;
107
108   if (p1 == p2 || n == 0)
109     return 0;
110
111   do
112     {
113       c1 = TOLOWER (*p1++);
114       c2 = TOLOWER (*p2++);
115       if (c1 == '\0' || c1 != c2)
116         return c1 - c2;
117     } while (--n > 0);
118
119   return c1 - c2;
120 }
121 #endif /* not HAVE_STRNCASECMP */
122
123 #ifndef HAVE_STRSTR
124 /* From GNU libc 2.3.5.  */
125
126 /*
127  * My personal strstr() implementation that beats most other algorithms.
128  * Until someone tells me otherwise, I assume that this is the
129  * fastest implementation of strstr() in C.
130  * I deliberately chose not to comment it.  You should have at least
131  * as much fun trying to understand it, as I had to write it :-).
132  *
133  * Stephen R. van den Berg, berg@pool.informatik.rwth-aachen.de */
134
135 typedef unsigned chartype;
136
137 #undef strstr
138
139 char *
140 strstr (const char *phaystack, const char *pneedle)
141 {
142   const unsigned char *haystack, *needle;
143   chartype b;
144   const unsigned char *rneedle;
145
146   haystack = (const unsigned char *) phaystack;
147
148   if ((b = *(needle = (const unsigned char *) pneedle)))
149     {
150       chartype c;
151       haystack--;               /* possible ANSI violation */
152
153       {
154         chartype a;
155         do
156           if (!(a = *++haystack))
157             goto ret0;
158         while (a != b);
159       }
160
161       if (!(c = *++needle))
162         goto foundneedle;
163       ++needle;
164       goto jin;
165
166       for (;;)
167         {
168           {
169             chartype a;
170             if (0)
171             jin:{
172                 if ((a = *++haystack) == c)
173                   goto crest;
174               }
175             else
176               a = *++haystack;
177             do
178               {
179                 for (; a != b; a = *++haystack)
180                   {
181                     if (!a)
182                       goto ret0;
183                     if ((a = *++haystack) == b)
184                       break;
185                     if (!a)
186                       goto ret0;
187                   }
188               }
189             while ((a = *++haystack) != c);
190           }
191         crest:
192           {
193             chartype a;
194             {
195               const unsigned char *rhaystack;
196               if (*(rhaystack = haystack-- + 1) == (a = *(rneedle = needle)))
197                 do
198                   {
199                     if (!a)
200                       goto foundneedle;
201                     if (*++rhaystack != (a = *++needle))
202                       break;
203                     if (!a)
204                       goto foundneedle;
205                   }
206                 while (*++rhaystack == (a = *++needle));
207               needle = rneedle; /* took the register-poor aproach */
208             }
209             if (!a)
210               break;
211           }
212         }
213     }
214 foundneedle:
215   return (char *) haystack;
216 ret0:
217   return 0;
218 }
219 #endif /* not HAVE_STRSTR */
220
221 #ifndef HAVE_STRPBRK
222 /* Find the first ocurrence in S of any character in ACCEPT.  */
223 char *
224 strpbrk (const char *s, const char *accept)
225 {
226   while (*s != '\0')
227     {
228       const char *a = accept;
229       while (*a != '\0')
230         if (*a++ == *s)
231           return (char *) s;
232       ++s;
233     }
234
235   return 0;
236 }
237 #endif /* HAVE_STRPBRK */
238
239 #ifndef HAVE_MKTIME
240 /* From GNU libc 2.0.  */
241
242 /* Copyright (C) 1993, 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
243    This file is part of the GNU C Library.
244    Contributed by Paul Eggert (eggert@twinsun.com).  */
245
246 #ifdef _LIBC
247 # define HAVE_LIMITS_H 1
248 # define HAVE_LOCALTIME_R 1
249 # define STDC_HEADERS 1
250 #endif
251
252 /* Assume that leap seconds are possible, unless told otherwise.
253    If the host has a `zic' command with a `-L leapsecondfilename' option,
254    then it supports leap seconds; otherwise it probably doesn't.  */
255 #ifndef LEAP_SECONDS_POSSIBLE
256 # define LEAP_SECONDS_POSSIBLE 1
257 #endif
258
259 #ifndef __P
260 # define __P(args) PARAMS (args)
261 #endif  /* Not __P.  */
262
263 #ifndef CHAR_BIT
264 # define CHAR_BIT 8
265 #endif
266
267 #ifndef INT_MIN
268 # define INT_MIN (~0 << (sizeof (int) * CHAR_BIT - 1))
269 #endif
270 #ifndef INT_MAX
271 # define INT_MAX (~0 - INT_MIN)
272 #endif
273
274 #ifndef TIME_T_MIN
275 /* The outer cast to time_t works around a bug in Cray C 5.0.3.0.  */
276 # define TIME_T_MIN ((time_t) \
277                     (0 < (time_t) -1 ? (time_t) 0 \
278                      : ~ (time_t) 0 << (sizeof (time_t) * CHAR_BIT - 1)))
279 #endif
280 #ifndef TIME_T_MAX
281 # define TIME_T_MAX (~ (time_t) 0 - TIME_T_MIN)
282 #endif
283
284 #define TM_YEAR_BASE 1900
285 #define EPOCH_YEAR 1970
286
287 #ifndef __isleap
288 /* Nonzero if YEAR is a leap year (every 4 years,
289    except every 100th isn't, and every 400th is).  */
290 # define __isleap(year) \
291   ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
292 #endif
293
294 /* How many days come before each month (0-12).  */
295 /* __mon_yday[][] is common to mktime and strptime implementations.
296    --abbotti */
297 const unsigned short int __mon_yday[2][13];
298 #ifndef NEED_MON_YDAY
299 # define NEED_MON_YDAY
300 #endif
301
302 static time_t ydhms_tm_diff __P ((int, int, int, int, int, const struct tm *));
303 time_t __mktime_internal __P ((struct tm *,
304                                struct tm *(*) (const time_t *, struct tm *),
305                                time_t *));
306
307
308 #ifdef _LIBC
309 # define localtime_r __localtime_r
310 #else
311 # if ! HAVE_LOCALTIME_R && ! defined localtime_r
312 /* Approximate localtime_r as best we can in its absence.  */
313 #  define localtime_r my_mktime_localtime_r
314 static struct tm *localtime_r __P ((const time_t *, struct tm *));
315 static struct tm *
316 localtime_r (t, tp)
317      const time_t *t;
318      struct tm *tp;
319 {
320   struct tm *l = localtime (t);
321   if (! l)
322     return 0;
323   *tp = *l;
324   return tp;
325 }
326 # endif /* ! HAVE_LOCALTIME_R && ! defined (localtime_r) */
327 #endif /* ! _LIBC */
328
329
330 /* Yield the difference between (YEAR-YDAY HOUR:MIN:SEC) and (*TP),
331    measured in seconds, ignoring leap seconds.
332    YEAR uses the same numbering as TM->tm_year.
333    All values are in range, except possibly YEAR.
334    If overflow occurs, yield the low order bits of the correct answer.  */
335 static time_t
336 ydhms_tm_diff (year, yday, hour, min, sec, tp)
337      int year, yday, hour, min, sec;
338      const struct tm *tp;
339 {
340   /* Compute intervening leap days correctly even if year is negative.
341      Take care to avoid int overflow.  time_t overflow is OK, since
342      only the low order bits of the correct time_t answer are needed.
343      Don't convert to time_t until after all divisions are done, since
344      time_t might be unsigned.  */
345   int a4 = (year >> 2) + (TM_YEAR_BASE >> 2) - ! (year & 3);
346   int b4 = (tp->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (tp->tm_year & 3);
347   int a100 = a4 / 25 - (a4 % 25 < 0);
348   int b100 = b4 / 25 - (b4 % 25 < 0);
349   int a400 = a100 >> 2;
350   int b400 = b100 >> 2;
351   int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
352   time_t years = year - (time_t) tp->tm_year;
353   time_t days = (365 * years + intervening_leap_days
354                  + (yday - tp->tm_yday));
355   return (60 * (60 * (24 * days + (hour - tp->tm_hour))
356                 + (min - tp->tm_min))
357           + (sec - tp->tm_sec));
358 }
359
360
361 static time_t localtime_offset;
362
363 /* Convert *TP to a time_t value.  */
364 time_t
365 mktime (tp)
366      struct tm *tp;
367 {
368 #ifdef _LIBC
369   /* POSIX.1 8.1.1 requires that whenever mktime() is called, the
370      time zone names contained in the external variable `tzname' shall
371      be set as if the tzset() function had been called.  */
372   __tzset ();
373 #endif
374
375   return __mktime_internal (tp, localtime_r, &localtime_offset);
376 }
377
378 /* Convert *TP to a time_t value, inverting
379    the monotonic and mostly-unit-linear conversion function CONVERT.
380    Use *OFFSET to keep track of a guess at the offset of the result,
381    compared to what the result would be for UTC without leap seconds.
382    If *OFFSET's guess is correct, only one CONVERT call is needed.  */
383 time_t
384 __mktime_internal (tp, convert, offset)
385      struct tm *tp;
386      struct tm *(*convert) __P ((const time_t *, struct tm *));
387      time_t *offset;
388 {
389   time_t t, dt, t0;
390   struct tm tm;
391
392   /* The maximum number of probes (calls to CONVERT) should be enough
393      to handle any combinations of time zone rule changes, solar time,
394      and leap seconds.  Posix.1 prohibits leap seconds, but some hosts
395      have them anyway.  */
396   int remaining_probes = 4;
397
398   /* Time requested.  Copy it in case CONVERT modifies *TP; this can
399      occur if TP is localtime's returned value and CONVERT is localtime.  */
400   int sec = tp->tm_sec;
401   int min = tp->tm_min;
402   int hour = tp->tm_hour;
403   int mday = tp->tm_mday;
404   int mon = tp->tm_mon;
405   int year_requested = tp->tm_year;
406   int isdst = tp->tm_isdst;
407
408   /* Ensure that mon is in range, and set year accordingly.  */
409   int mon_remainder = mon % 12;
410   int negative_mon_remainder = mon_remainder < 0;
411   int mon_years = mon / 12 - negative_mon_remainder;
412   int year = year_requested + mon_years;
413
414   /* The other values need not be in range:
415      the remaining code handles minor overflows correctly,
416      assuming int and time_t arithmetic wraps around.
417      Major overflows are caught at the end.  */
418
419   /* Calculate day of year from year, month, and day of month.
420      The result need not be in range.  */
421   int yday = ((__mon_yday[__isleap (year + TM_YEAR_BASE)]
422                [mon_remainder + 12 * negative_mon_remainder])
423               + mday - 1);
424
425   int sec_requested = sec;
426 #if LEAP_SECONDS_POSSIBLE
427   /* Handle out-of-range seconds specially,
428      since ydhms_tm_diff assumes every minute has 60 seconds.  */
429   if (sec < 0)
430     sec = 0;
431   if (59 < sec)
432     sec = 59;
433 #endif
434
435   /* Invert CONVERT by probing.  First assume the same offset as last time.
436      Then repeatedly use the error to improve the guess.  */
437
438   tm.tm_year = EPOCH_YEAR - TM_YEAR_BASE;
439   tm.tm_yday = tm.tm_hour = tm.tm_min = tm.tm_sec = 0;
440   t0 = ydhms_tm_diff (year, yday, hour, min, sec, &tm);
441
442   for (t = t0 + *offset;
443        (dt = ydhms_tm_diff (year, yday, hour, min, sec, (*convert) (&t, &tm)));
444        t += dt)
445     if (--remaining_probes == 0)
446       return -1;
447
448   /* Check whether tm.tm_isdst has the requested value, if any.  */
449   if (0 <= isdst && 0 <= tm.tm_isdst)
450     {
451       int dst_diff = (isdst != 0) - (tm.tm_isdst != 0);
452       if (dst_diff)
453         {
454           /* Move two hours in the direction indicated by the disagreement,
455              probe some more, and switch to a new time if found.
456              The largest known fallback due to daylight savings is two hours:
457              once, in Newfoundland, 1988-10-30 02:00 -> 00:00.  */
458           time_t ot = t - 2 * 60 * 60 * dst_diff;
459           while (--remaining_probes != 0)
460             {
461               struct tm otm;
462               if (! (dt = ydhms_tm_diff (year, yday, hour, min, sec,
463                                          (*convert) (&ot, &otm))))
464                 {
465                   t = ot;
466                   tm = otm;
467                   break;
468                 }
469               if ((ot += dt) == t)
470                 break;  /* Avoid a redundant probe.  */
471             }
472         }
473     }
474
475   *offset = t - t0;
476
477 #if LEAP_SECONDS_POSSIBLE
478   if (sec_requested != tm.tm_sec)
479     {
480       /* Adjust time to reflect the tm_sec requested, not the normalized value.
481          Also, repair any damage from a false match due to a leap second.  */
482       t += sec_requested - sec + (sec == 0 && tm.tm_sec == 60);
483       (*convert) (&t, &tm);
484     }
485 #endif
486
487   if (TIME_T_MAX / INT_MAX / 366 / 24 / 60 / 60 < 3)
488     {
489       /* time_t isn't large enough to rule out overflows in ydhms_tm_diff,
490          so check for major overflows.  A gross check suffices,
491          since if t has overflowed, it is off by a multiple of
492          TIME_T_MAX - TIME_T_MIN + 1.  So ignore any component of
493          the difference that is bounded by a small value.  */
494
495       double dyear = (double) year_requested + mon_years - tm.tm_year;
496       double dday = 366 * dyear + mday;
497       double dsec = 60 * (60 * (24 * dday + hour) + min) + sec_requested;
498
499       if (TIME_T_MAX / 3 - TIME_T_MIN / 3 < (dsec < 0 ? - dsec : dsec))
500         return -1;
501     }
502
503   *tp = tm;
504   return t;
505 }
506
507 #ifdef weak_alias
508 weak_alias (mktime, timelocal)
509 #endif
510 #endif /* not HAVE_MKTIME */
511
512
513 #ifndef HAVE_STRPTIME
514 /* From GNU libc 2.1.3.  */
515 /* Ulrich, thanks for helping me out with this!  --hniksic  */
516
517 /* strptime - Convert a string representation of time to a time value.
518    Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
519    This file is part of the GNU C Library.
520    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.  */
521
522 /* XXX This version of the implementation is not really complete.
523    Some of the fields cannot add information alone.  But if seeing
524    some of them in the same format (such as year, week and weekday)
525    this is enough information for determining the date.  */
526
527 #ifndef __P
528 # define __P(args) PARAMS (args)
529 #endif /* not __P */
530
531 #if ! HAVE_LOCALTIME_R && ! defined localtime_r
532 # ifdef _LIBC
533 #  define localtime_r __localtime_r
534 # else
535 /* Approximate localtime_r as best we can in its absence.  */
536 #  define localtime_r my_localtime_r
537 static struct tm *localtime_r __P ((const time_t *, struct tm *));
538 static struct tm *
539 localtime_r (t, tp)
540      const time_t *t;
541      struct tm *tp;
542 {
543   struct tm *l = localtime (t);
544   if (! l)
545     return 0;
546   *tp = *l;
547   return tp;
548 }
549 # endif /* ! _LIBC */
550 #endif /* ! HAVE_LOCALTIME_R && ! defined (localtime_r) */
551
552
553 #define match_char(ch1, ch2) if (ch1 != ch2) return NULL
554 #if defined __GNUC__ && __GNUC__ >= 2
555 # define match_string(cs1, s2) \
556   ({ size_t len = strlen (cs1);                                               \
557      int result = strncasecmp ((cs1), (s2), len) == 0;                        \
558      if (result) (s2) += len;                                                 \
559      result; })
560 #else
561 /* Oh come on.  Get a reasonable compiler.  */
562 # define match_string(cs1, s2) \
563   (strncasecmp ((cs1), (s2), strlen (cs1)) ? 0 : ((s2) += strlen (cs1), 1))
564 #endif
565 /* We intentionally do not use isdigit() for testing because this will
566    lead to problems with the wide character version.  */
567 #define get_number(from, to, n) \
568   do {                                                                        \
569     int __n = n;                                                              \
570     val = 0;                                                                  \
571     while (*rp == ' ')                                                        \
572       ++rp;                                                                   \
573     if (*rp < '0' || *rp > '9')                                               \
574       return NULL;                                                            \
575     do {                                                                      \
576       val *= 10;                                                              \
577       val += *rp++ - '0';                                                     \
578     } while (--__n > 0 && val * 10 <= to && *rp >= '0' && *rp <= '9');        \
579     if (val < from || val > to)                                               \
580       return NULL;                                                            \
581   } while (0)
582 #ifdef _NL_CURRENT
583 /* Added check for __GNUC__ extensions here for Wget. --abbotti */
584 # if defined __GNUC__ && __GNUC__ >= 2
585 #  define get_alt_number(from, to, n) \
586   ({                                                                          \
587     __label__ do_normal;                                                      \
588     if (*decided != raw)                                                      \
589       {                                                                       \
590         const char *alts = _NL_CURRENT (LC_TIME, ALT_DIGITS);                 \
591         int __n = n;                                                          \
592         int any = 0;                                                          \
593         while (*rp == ' ')                                                    \
594           ++rp;                                                               \
595         val = 0;                                                              \
596         do {                                                                  \
597           val *= 10;                                                          \
598           while (*alts != '\0')                                               \
599             {                                                                 \
600               size_t len = strlen (alts);                                     \
601               if (strncasecmp (alts, rp, len) == 0)                           \
602                 break;                                                        \
603               alts += len + 1;                                                \
604               ++val;                                                          \
605             }                                                                 \
606           if (*alts == '\0')                                                  \
607             {                                                                 \
608               if (*decided == not && ! any)                                   \
609                 goto do_normal;                                               \
610               /* If we haven't read anything it's an error.  */               \
611               if (! any)                                                      \
612                 return NULL;                                                  \
613               /* Correct the premature multiplication.  */                    \
614               val /= 10;                                                      \
615               break;                                                          \
616             }                                                                 \
617           else                                                                \
618             *decided = loc;                                                   \
619         } while (--__n > 0 && val * 10 <= to);                                \
620         if (val < from || val > to)                                           \
621           return NULL;                                                        \
622       }                                                                       \
623     else                                                                      \
624       {                                                                       \
625        do_normal:                                                             \
626         get_number (from, to, n);                                             \
627       }                                                                       \
628     0;                                                                        \
629   })
630 # else
631 #  define get_alt_number(from, to, n) \
632   do {
633     if (*decided != raw)                                                      \
634       {                                                                       \
635         const char *alts = _NL_CURRENT (LC_TIME, ALT_DIGITS);                 \
636         int __n = n;                                                          \
637         int any = 0;                                                          \
638         while (*rp == ' ')                                                    \
639           ++rp;                                                               \
640         val = 0;                                                              \
641         do {                                                                  \
642           val *= 10;                                                          \
643           while (*alts != '\0')                                               \
644             {                                                                 \
645               size_t len = strlen (alts);                                     \
646               if (strncasecmp (alts, rp, len) == 0)                           \
647                 break;                                                        \
648               alts += len + 1;                                                \
649               ++val;                                                          \
650             }                                                                 \
651           if (*alts == '\0')                                                  \
652             {                                                                 \
653               if (*decided == not && ! any)                                   \
654                 goto do_normal;                                               \
655               /* If we haven't read anything it's an error.  */               \
656               if (! any)                                                      \
657                 return NULL;                                                  \
658               /* Correct the premature multiplication.  */                    \
659               val /= 10;                                                      \
660               break;                                                          \
661             }                                                                 \
662           else                                                                \
663             *decided = loc;                                                   \
664         } while (--__n > 0 && val * 10 <= to);                                \
665         if (val < from || val > to)                                           \
666           return NULL;                                                        \
667       }                                                                       \
668     else                                                                      \
669       {                                                                       \
670        do_normal:                                                             \
671         get_number (from, to, n);                                             \
672       }                                                                       \
673   } while (0)
674 # endif /* defined __GNUC__ && __GNUC__ >= 2 */
675 #else
676 # define get_alt_number(from, to, n) \
677   /* We don't have the alternate representation.  */                          \
678   get_number(from, to, n)
679 #endif
680 #define recursive(new_fmt) \
681   (*(new_fmt) != '\0'                                                         \
682    && (rp = strptime_internal (rp, (new_fmt), tm, decided)) != NULL)
683
684
685 #ifdef _LIBC
686 /* This is defined in locale/C-time.c in the GNU libc.  */
687 extern const struct locale_data _nl_C_LC_TIME;
688 extern const unsigned short int __mon_yday[2][13];
689
690 # define weekday_name (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (DAY_1)].string)
691 # define ab_weekday_name \
692   (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (ABDAY_1)].string)
693 # define month_name (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (MON_1)].string)
694 # define ab_month_name (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (ABMON_1)].string)
695 # define HERE_D_T_FMT (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (D_T_FMT)].string)
696 # define HERE_D_FMT (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (D_FMT)].string)
697 # define HERE_AM_STR (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (AM_STR)].string)
698 # define HERE_PM_STR (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (PM_STR)].string)
699 # define HERE_T_FMT_AMPM \
700   (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (T_FMT_AMPM)].string)
701 # define HERE_T_FMT (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (T_FMT)].string)
702
703 # define strncasecmp(s1, s2, n) __strncasecmp (s1, s2, n)
704 #else
705 static char const weekday_name[][10] =
706   {
707     "Sunday", "Monday", "Tuesday", "Wednesday",
708     "Thursday", "Friday", "Saturday"
709   };
710 static char const ab_weekday_name[][4] =
711   {
712     "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
713   };
714 static char const month_name[][10] =
715   {
716     "January", "February", "March", "April", "May", "June",
717     "July", "August", "September", "October", "November", "December"
718   };
719 static char const ab_month_name[][4] =
720   {
721     "Jan", "Feb", "Mar", "Apr", "May", "Jun",
722     "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
723   };
724 # define HERE_D_T_FMT "%a %b %e %H:%M:%S %Y"
725 # define HERE_D_FMT "%m/%d/%y"
726 # define HERE_AM_STR "AM"
727 # define HERE_PM_STR "PM"
728 # define HERE_T_FMT_AMPM "%I:%M:%S %p"
729 # define HERE_T_FMT "%H:%M:%S"
730
731 /* __mon_yday[][] is common to mktime and strptime implementations.
732    --abbotti */
733 const unsigned short int __mon_yday[2][13];
734 # ifndef NEED_MON_YDAY
735 #  define NEED_MON_YDAY
736 # endif
737 #endif
738
739 /* Status of lookup: do we use the locale data or the raw data?  */
740 enum locale_status { not, loc, raw };
741
742
743 #ifndef __isleap
744 /* Nonzero if YEAR is a leap year (every 4 years,
745    except every 100th isn't, and every 400th is).  */
746 # define __isleap(year) \
747   ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
748 #endif
749
750 /* Compute the day of the week.  */
751 static void
752 day_of_the_week (struct tm *tm)
753 {
754   /* We know that January 1st 1970 was a Thursday (= 4).  Compute the
755      the difference between this data in the one on TM and so determine
756      the weekday.  */
757   int corr_year = 1900 + tm->tm_year - (tm->tm_mon < 2);
758   int wday = (-473
759               + (365 * (tm->tm_year - 70))
760               + (corr_year / 4)
761               - ((corr_year / 4) / 25) + ((corr_year / 4) % 25 < 0)
762               + (((corr_year / 4) / 25) / 4)
763               + __mon_yday[0][tm->tm_mon]
764               + tm->tm_mday - 1);
765   tm->tm_wday = ((wday % 7) + 7) % 7;
766 }
767
768 /* Compute the day of the year.  */
769 static void
770 day_of_the_year (struct tm *tm)
771 {
772   tm->tm_yday = (__mon_yday[__isleap (1900 + tm->tm_year)][tm->tm_mon]
773                  + (tm->tm_mday - 1));
774 }
775
776 static char *
777 #ifdef _LIBC
778 internal_function
779 #endif
780 strptime_internal __P ((const char *buf, const char *format, struct tm *tm,
781                         enum locale_status *decided));
782
783 static char *
784 #ifdef _LIBC
785 internal_function
786 #endif
787 strptime_internal (rp, fmt, tm, decided)
788      const char *rp;
789      const char *fmt;
790      struct tm *tm;
791      enum locale_status *decided;
792 {
793 #ifdef _NL_CURRENT
794   const char *rp_backup;
795 #endif
796   int cnt;
797   size_t val;
798   int have_I, is_pm;
799   int century, want_century;
800   int have_wday, want_xday;
801   int have_yday;
802   int have_mon, have_mday;
803
804   have_I = is_pm = 0;
805   century = -1;
806   want_century = 0;
807   have_wday = want_xday = have_yday = have_mon = have_mday = 0;
808
809   while (*fmt != '\0')
810     {
811       /* A white space in the format string matches 0 more or white
812          space in the input string.  */
813       if (ISSPACE (*fmt))
814         {
815           while (ISSPACE (*rp))
816             ++rp;
817           ++fmt;
818           continue;
819         }
820
821       /* Any character but `%' must be matched by the same character
822          in the iput string.  */
823       if (*fmt != '%')
824         {
825           match_char (*fmt++, *rp++);
826           continue;
827         }
828
829       ++fmt;
830 #ifndef _NL_CURRENT
831       /* We need this for handling the `E' modifier.  */
832     start_over:
833 #endif
834
835 #ifdef _NL_CURRENT
836       /* Make back up of current processing pointer.  */
837       rp_backup = rp;
838 #endif
839
840       switch (*fmt++)
841         {
842         case '%':
843           /* Match the `%' character itself.  */
844           match_char ('%', *rp++);
845           break;
846         case 'a':
847         case 'A':
848           /* Match day of week.  */
849           for (cnt = 0; cnt < 7; ++cnt)
850             {
851 #ifdef _NL_CURRENT
852               if (*decided !=raw)
853                 {
854                   if (match_string (_NL_CURRENT (LC_TIME, DAY_1 + cnt), rp))
855                     {
856                       if (*decided == not
857                           && strcmp (_NL_CURRENT (LC_TIME, DAY_1 + cnt),
858                                      weekday_name[cnt]))
859                         *decided = loc;
860                       break;
861                     }
862                   if (match_string (_NL_CURRENT (LC_TIME, ABDAY_1 + cnt), rp))
863                     {
864                       if (*decided == not
865                           && strcmp (_NL_CURRENT (LC_TIME, ABDAY_1 + cnt),
866                                      ab_weekday_name[cnt]))
867                         *decided = loc;
868                       break;
869                     }
870                 }
871 #endif
872               if (*decided != loc
873                   && (match_string (weekday_name[cnt], rp)
874                       || match_string (ab_weekday_name[cnt], rp)))
875                 {
876                   *decided = raw;
877                   break;
878                 }
879             }
880           if (cnt == 7)
881             /* Does not match a weekday name.  */
882             return NULL;
883           tm->tm_wday = cnt;
884           have_wday = 1;
885           break;
886         case 'b':
887         case 'B':
888         case 'h':
889           /* Match month name.  */
890           for (cnt = 0; cnt < 12; ++cnt)
891             {
892 #ifdef _NL_CURRENT
893               if (*decided !=raw)
894                 {
895                   if (match_string (_NL_CURRENT (LC_TIME, MON_1 + cnt), rp))
896                     {
897                       if (*decided == not
898                           && strcmp (_NL_CURRENT (LC_TIME, MON_1 + cnt),
899                                      month_name[cnt]))
900                         *decided = loc;
901                       break;
902                     }
903                   if (match_string (_NL_CURRENT (LC_TIME, ABMON_1 + cnt), rp))
904                     {
905                       if (*decided == not
906                           && strcmp (_NL_CURRENT (LC_TIME, ABMON_1 + cnt),
907                                      ab_month_name[cnt]))
908                         *decided = loc;
909                       break;
910                     }
911                 }
912 #endif
913               if (match_string (month_name[cnt], rp)
914                   || match_string (ab_month_name[cnt], rp))
915                 {
916                   *decided = raw;
917                   break;
918                 }
919             }
920           if (cnt == 12)
921             /* Does not match a month name.  */
922             return NULL;
923           tm->tm_mon = cnt;
924           want_xday = 1;
925           break;
926         case 'c':
927           /* Match locale's date and time format.  */
928 #ifdef _NL_CURRENT
929           if (*decided != raw)
930             {
931               if (!recursive (_NL_CURRENT (LC_TIME, D_T_FMT)))
932                 {
933                   if (*decided == loc)
934                     return NULL;
935                   else
936                     rp = rp_backup;
937                 }
938               else
939                 {
940                   if (*decided == not &&
941                       strcmp (_NL_CURRENT (LC_TIME, D_T_FMT), HERE_D_T_FMT))
942                     *decided = loc;
943                   want_xday = 1;
944                   break;
945                 }
946               *decided = raw;
947             }
948 #endif
949           if (!recursive (HERE_D_T_FMT))
950             return NULL;
951           want_xday = 1;
952           break;
953         case 'C':
954           /* Match century number.  */
955           get_number (0, 99, 2);
956           century = val;
957           want_xday = 1;
958           break;
959         case 'd':
960         case 'e':
961           /* Match day of month.  */
962           get_number (1, 31, 2);
963           tm->tm_mday = val;
964           have_mday = 1;
965           want_xday = 1;
966           break;
967         case 'F':
968           if (!recursive ("%Y-%m-%d"))
969             return NULL;
970           want_xday = 1;
971           break;
972         case 'x':
973 #ifdef _NL_CURRENT
974           if (*decided != raw)
975             {
976               if (!recursive (_NL_CURRENT (LC_TIME, D_FMT)))
977                 {
978                   if (*decided == loc)
979                     return NULL;
980                   else
981                     rp = rp_backup;
982                 }
983               else
984                 {
985                   if (*decided == not
986                       && strcmp (_NL_CURRENT (LC_TIME, D_FMT), HERE_D_FMT))
987                     *decided = loc;
988                   want_xday = 1;
989                   break;
990                 }
991               *decided = raw;
992             }
993 #endif
994           /* Fall through.  */
995         case 'D':
996           /* Match standard day format.  */
997           if (!recursive (HERE_D_FMT))
998             return NULL;
999           want_xday = 1;
1000           break;
1001         case 'k':
1002         case 'H':
1003           /* Match hour in 24-hour clock.  */
1004           get_number (0, 23, 2);
1005           tm->tm_hour = val;
1006           have_I = 0;
1007           break;
1008         case 'I':
1009           /* Match hour in 12-hour clock.  */
1010           get_number (1, 12, 2);
1011           tm->tm_hour = val % 12;
1012           have_I = 1;
1013           break;
1014         case 'j':
1015           /* Match day number of year.  */
1016           get_number (1, 366, 3);
1017           tm->tm_yday = val - 1;
1018           have_yday = 1;
1019           break;
1020         case 'm':
1021           /* Match number of month.  */
1022           get_number (1, 12, 2);
1023           tm->tm_mon = val - 1;
1024           have_mon = 1;
1025           want_xday = 1;
1026           break;
1027         case 'M':
1028           /* Match minute.  */
1029           get_number (0, 59, 2);
1030           tm->tm_min = val;
1031           break;
1032         case 'n':
1033         case 't':
1034           /* Match any white space.  */
1035           while (ISSPACE (*rp))
1036             ++rp;
1037           break;
1038         case 'p':
1039           /* Match locale's equivalent of AM/PM.  */
1040 #ifdef _NL_CURRENT
1041           if (*decided != raw)
1042             {
1043               if (match_string (_NL_CURRENT (LC_TIME, AM_STR), rp))
1044                 {
1045                   if (strcmp (_NL_CURRENT (LC_TIME, AM_STR), HERE_AM_STR))
1046                     *decided = loc;
1047                   break;
1048                 }
1049               if (match_string (_NL_CURRENT (LC_TIME, PM_STR), rp))
1050                 {
1051                   if (strcmp (_NL_CURRENT (LC_TIME, PM_STR), HERE_PM_STR))
1052                     *decided = loc;
1053                   is_pm = 1;
1054                   break;
1055                 }
1056               *decided = raw;
1057             }
1058 #endif
1059           if (!match_string (HERE_AM_STR, rp))
1060             if (match_string (HERE_PM_STR, rp))
1061               is_pm = 1;
1062             else
1063               return NULL;
1064           break;
1065         case 'r':
1066 #ifdef _NL_CURRENT
1067           if (*decided != raw)
1068             {
1069               if (!recursive (_NL_CURRENT (LC_TIME, T_FMT_AMPM)))
1070                 {
1071                   if (*decided == loc)
1072                     return NULL;
1073                   else
1074                     rp = rp_backup;
1075                 }
1076               else
1077                 {
1078                   if (*decided == not &&
1079                       strcmp (_NL_CURRENT (LC_TIME, T_FMT_AMPM),
1080                               HERE_T_FMT_AMPM))
1081                     *decided = loc;
1082                   break;
1083                 }
1084               *decided = raw;
1085             }
1086 #endif
1087           if (!recursive (HERE_T_FMT_AMPM))
1088             return NULL;
1089           break;
1090         case 'R':
1091           if (!recursive ("%H:%M"))
1092             return NULL;
1093           break;
1094         case 's':
1095           {
1096             /* The number of seconds may be very high so we cannot use
1097                the `get_number' macro.  Instead read the number
1098                character for character and construct the result while
1099                doing this.  */
1100             time_t secs = 0;
1101             if (*rp < '0' || *rp > '9')
1102               /* We need at least one digit.  */
1103               return NULL;
1104
1105             do
1106               {
1107                 secs *= 10;
1108                 secs += *rp++ - '0';
1109               }
1110             while (*rp >= '0' && *rp <= '9');
1111
1112             if (localtime_r (&secs, tm) == NULL)
1113               /* Error in function.  */
1114               return NULL;
1115           }
1116           break;
1117         case 'S':
1118           get_number (0, 61, 2);
1119           tm->tm_sec = val;
1120           break;
1121         case 'X':
1122 #ifdef _NL_CURRENT
1123           if (*decided != raw)
1124             {
1125               if (!recursive (_NL_CURRENT (LC_TIME, T_FMT)))
1126                 {
1127                   if (*decided == loc)
1128                     return NULL;
1129                   else
1130                     rp = rp_backup;
1131                 }
1132               else
1133                 {
1134                   if (strcmp (_NL_CURRENT (LC_TIME, T_FMT), HERE_T_FMT))
1135                     *decided = loc;
1136                   break;
1137                 }
1138               *decided = raw;
1139             }
1140 #endif
1141           /* Fall through.  */
1142         case 'T':
1143           if (!recursive (HERE_T_FMT))
1144             return NULL;
1145           break;
1146         case 'u':
1147           get_number (1, 7, 1);
1148           tm->tm_wday = val % 7;
1149           have_wday = 1;
1150           break;
1151         case 'g':
1152           get_number (0, 99, 2);
1153           /* XXX This cannot determine any field in TM.  */
1154           break;
1155         case 'G':
1156           if (*rp < '0' || *rp > '9')
1157             return NULL;
1158           /* XXX Ignore the number since we would need some more
1159              information to compute a real date.  */
1160           do
1161             ++rp;
1162           while (*rp >= '0' && *rp <= '9');
1163           break;
1164         case 'U':
1165         case 'V':
1166         case 'W':
1167           get_number (0, 53, 2);
1168           /* XXX This cannot determine any field in TM without some
1169              information.  */
1170           break;
1171         case 'w':
1172           /* Match number of weekday.  */
1173           get_number (0, 6, 1);
1174           tm->tm_wday = val;
1175           have_wday = 1;
1176           break;
1177         case 'y':
1178           /* Match year within century.  */
1179           get_number (0, 99, 2);
1180           /* The "Year 2000: The Millennium Rollover" paper suggests that
1181              values in the range 69-99 refer to the twentieth century.  */
1182           tm->tm_year = val >= 69 ? val : val + 100;
1183           /* Indicate that we want to use the century, if specified.  */
1184           want_century = 1;
1185           want_xday = 1;
1186           break;
1187         case 'Y':
1188           /* Match year including century number.  */
1189           get_number (0, 9999, 4);
1190           tm->tm_year = val - 1900;
1191           want_century = 0;
1192           want_xday = 1;
1193           break;
1194         case 'Z':
1195           /* XXX How to handle this?  */
1196           break;
1197         case 'E':
1198 #ifdef _NL_CURRENT
1199           switch (*fmt++)
1200             {
1201             case 'c':
1202               /* Match locale's alternate date and time format.  */
1203               if (*decided != raw)
1204                 {
1205                   const char *fmt = _NL_CURRENT (LC_TIME, ERA_D_T_FMT);
1206
1207                   if (*fmt == '\0')
1208                     fmt = _NL_CURRENT (LC_TIME, D_T_FMT);
1209
1210                   if (!recursive (fmt))
1211                     {
1212                       if (*decided == loc)
1213                         return NULL;
1214                       else
1215                         rp = rp_backup;
1216                     }
1217                   else
1218                     {
1219                       if (strcmp (fmt, HERE_D_T_FMT))
1220                         *decided = loc;
1221                       want_xday = 1;
1222                       break;
1223                     }
1224                   *decided = raw;
1225                 }
1226               /* The C locale has no era information, so use the
1227                  normal representation.  */
1228               if (!recursive (HERE_D_T_FMT))
1229                 return NULL;
1230               want_xday = 1;
1231               break;
1232             case 'C':
1233             case 'y':
1234             case 'Y':
1235               /* Match name of base year in locale's alternate
1236                  representation.  */
1237               /* XXX This is currently not implemented.  It should
1238                  use the value _NL_CURRENT (LC_TIME, ERA).  */
1239               break;
1240             case 'x':
1241               if (*decided != raw)
1242                 {
1243                   const char *fmt = _NL_CURRENT (LC_TIME, ERA_D_FMT);
1244
1245                   if (*fmt == '\0')
1246                     fmt = _NL_CURRENT (LC_TIME, D_FMT);
1247
1248                   if (!recursive (fmt))
1249                     {
1250                       if (*decided == loc)
1251                         return NULL;
1252                       else
1253                         rp = rp_backup;
1254                     }
1255                   else
1256                     {
1257                       if (strcmp (fmt, HERE_D_FMT))
1258                         *decided = loc;
1259                       break;
1260                     }
1261                   *decided = raw;
1262                 }
1263               if (!recursive (HERE_D_FMT))
1264                 return NULL;
1265               break;
1266             case 'X':
1267               if (*decided != raw)
1268                 {
1269                   const char *fmt = _NL_CURRENT (LC_TIME, ERA_T_FMT);
1270
1271                   if (*fmt == '\0')
1272                     fmt = _NL_CURRENT (LC_TIME, T_FMT);
1273
1274                   if (!recursive (fmt))
1275                     {
1276                       if (*decided == loc)
1277                         return NULL;
1278                       else
1279                         rp = rp_backup;
1280                     }
1281                   else
1282                     {
1283                       if (strcmp (fmt, HERE_T_FMT))
1284                         *decided = loc;
1285                       break;
1286                     }
1287                   *decided = raw;
1288                 }
1289               if (!recursive (HERE_T_FMT))
1290                 return NULL;
1291               break;
1292             default:
1293               return NULL;
1294             }
1295           break;
1296 #else
1297           /* We have no information about the era format.  Just use
1298              the normal format.  */
1299           if (*fmt != 'c' && *fmt != 'C' && *fmt != 'y' && *fmt != 'Y'
1300               && *fmt != 'x' && *fmt != 'X')
1301             /* This is an illegal format.  */
1302             return NULL;
1303
1304           goto start_over;
1305 #endif
1306         case 'O':
1307           switch (*fmt++)
1308             {
1309             case 'd':
1310             case 'e':
1311               /* Match day of month using alternate numeric symbols.  */
1312               get_alt_number (1, 31, 2);
1313               tm->tm_mday = val;
1314               have_mday = 1;
1315               want_xday = 1;
1316               break;
1317             case 'H':
1318               /* Match hour in 24-hour clock using alternate numeric
1319                  symbols.  */
1320               get_alt_number (0, 23, 2);
1321               tm->tm_hour = val;
1322               have_I = 0;
1323               break;
1324             case 'I':
1325               /* Match hour in 12-hour clock using alternate numeric
1326                  symbols.  */
1327               get_alt_number (1, 12, 2);
1328               tm->tm_hour = val - 1;
1329               have_I = 1;
1330               break;
1331             case 'm':
1332               /* Match month using alternate numeric symbols.  */
1333               get_alt_number (1, 12, 2);
1334               tm->tm_mon = val - 1;
1335               have_mon = 1;
1336               want_xday = 1;
1337               break;
1338             case 'M':
1339               /* Match minutes using alternate numeric symbols.  */
1340               get_alt_number (0, 59, 2);
1341               tm->tm_min = val;
1342               break;
1343             case 'S':
1344               /* Match seconds using alternate numeric symbols.  */
1345               get_alt_number (0, 61, 2);
1346               tm->tm_sec = val;
1347               break;
1348             case 'U':
1349             case 'V':
1350             case 'W':
1351               get_alt_number (0, 53, 2);
1352               /* XXX This cannot determine any field in TM without
1353                  further information.  */
1354               break;
1355             case 'w':
1356               /* Match number of weekday using alternate numeric symbols.  */
1357               get_alt_number (0, 6, 1);
1358               tm->tm_wday = val;
1359               have_wday = 1;
1360               break;
1361             case 'y':
1362               /* Match year within century using alternate numeric symbols.  */
1363               get_alt_number (0, 99, 2);
1364               tm->tm_year = val >= 69 ? val : val + 100;
1365               want_xday = 1;
1366               break;
1367             default:
1368               return NULL;
1369             }
1370           break;
1371         default:
1372           return NULL;
1373         }
1374     }
1375
1376   if (have_I && is_pm)
1377     tm->tm_hour += 12;
1378
1379   if (century != -1)
1380     {
1381       if (want_century)
1382         tm->tm_year = tm->tm_year % 100 + (century - 19) * 100;
1383       else
1384         /* Only the century, but not the year.  Strange, but so be it.  */
1385         tm->tm_year = (century - 19) * 100;
1386     }
1387
1388   if (want_xday && !have_wday) {
1389       if ( !(have_mon && have_mday) && have_yday)  {
1390           /* we don't have tm_mon and/or tm_mday, compute them */
1391           int t_mon = 0;
1392           while (__mon_yday[__isleap(1900 + tm->tm_year)][t_mon] <= tm->tm_yday)
1393               t_mon++;
1394           if (!have_mon)
1395               tm->tm_mon = t_mon - 1;
1396           if (!have_mday)
1397               tm->tm_mday = tm->tm_yday - __mon_yday[__isleap(1900 + tm->tm_year)][t_mon - 1] + 1;
1398       }
1399       day_of_the_week (tm);
1400   }
1401   if (want_xday && !have_yday)
1402     day_of_the_year (tm);
1403
1404   return (char *) rp;
1405 }
1406
1407
1408 char *
1409 strptime (buf, format, tm)
1410      const char *buf;
1411      const char *format;
1412      struct tm *tm;
1413 {
1414   enum locale_status decided;
1415 #ifdef _NL_CURRENT
1416   decided = not;
1417 #else
1418   decided = raw;
1419 #endif
1420   return strptime_internal (buf, format, tm, &decided);
1421 }
1422 #endif /* not HAVE_STRPTIME */
1423
1424 #ifdef NEED_MON_YDAY
1425 /* __mon_yday[][] is common to mktime and strptime implementations.
1426    --abbotti */
1427 const unsigned short int __mon_yday[2][13] =
1428   {
1429     /* Normal years.  */
1430     { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
1431     /* Leap years.  */
1432     { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
1433   };
1434 #endif
1435
1436 #ifndef HAVE_MEMMOVE
1437 void *
1438 memmove (char *dest, const char *source, unsigned length)
1439 {
1440   char *d0 = dest;
1441   if (source < dest)
1442     /* Moving from low mem to hi mem; start at end.  */
1443     for (source += length, dest += length; length; --length)
1444       *--dest = *--source;
1445   else if (source != dest)
1446     {
1447       /* Moving from hi mem to low mem; start at beginning.  */
1448       for (; length; --length)
1449         *dest++ = *source++;
1450     }
1451   return (void *) d0;
1452 }
1453 #endif /* not HAVE_MEMMOVE */
1454
1455 /* fnmatch is a POSIX function, but we include an implementation for
1456    the sake of systems that don't have it.  Furthermore, according to
1457    anecdotal evidence, historical implementations of fnmatch are buggy
1458    and unreliable.  So we use our version, except when compiling under
1459    systems where fnmatch is known to work (currently glibc.)  */
1460
1461 #ifndef SYSTEM_FNMATCH
1462
1463 #define __FNM_FLAGS     (FNM_PATHNAME | FNM_NOESCAPE | FNM_PERIOD)
1464
1465 /* Match STRING against the filename pattern PATTERN, returning zero
1466    if it matches, FNM_NOMATCH if not.  This implementation comes from
1467    an earlier version of GNU Bash.  (It doesn't make sense to update
1468    it with a newer version because it adds a lot of features Wget
1469    doesn't use or care about.)  */
1470
1471 int
1472 fnmatch (const char *pattern, const char *string, int flags)
1473 {
1474   register const char *p = pattern, *n = string;
1475   register char c;
1476
1477   if ((flags & ~__FNM_FLAGS) != 0)
1478     {
1479       errno = EINVAL;
1480       return (-1);
1481     }
1482
1483   while ((c = *p++) != '\0')
1484     {
1485       switch (c)
1486         {
1487         case '?':
1488           if (*n == '\0')
1489             return (FNM_NOMATCH);
1490           else if ((flags & FNM_PATHNAME) && *n == '/')
1491             return (FNM_NOMATCH);
1492           else if ((flags & FNM_PERIOD) && *n == '.' &&
1493                    (n == string || ((flags & FNM_PATHNAME) && n[-1] == '/')))
1494             return (FNM_NOMATCH);
1495           break;
1496
1497         case '\\':
1498           if (!(flags & FNM_NOESCAPE))
1499             c = *p++;
1500           if (*n != c)
1501             return (FNM_NOMATCH);
1502           break;
1503
1504         case '*':
1505           if ((flags & FNM_PERIOD) && *n == '.' &&
1506               (n == string || ((flags & FNM_PATHNAME) && n[-1] == '/')))
1507             return (FNM_NOMATCH);
1508
1509           for (c = *p++; c == '?' || c == '*'; c = *p++, ++n)
1510             if (((flags & FNM_PATHNAME) && *n == '/') ||
1511                 (c == '?' && *n == '\0'))
1512               return (FNM_NOMATCH);
1513
1514           if (c == '\0')
1515             return (0);
1516
1517           {
1518             char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c;
1519             for (--p; *n != '\0'; ++n)
1520               if ((c == '[' || *n == c1) &&
1521                   fnmatch (p, n, flags & ~FNM_PERIOD) == 0)
1522                 return (0);
1523             return (FNM_NOMATCH);
1524           }
1525
1526         case '[':
1527           {
1528             /* Nonzero if the sense of the character class is
1529                inverted.  */
1530             register int not;
1531
1532             if (*n == '\0')
1533               return (FNM_NOMATCH);
1534
1535             if ((flags & FNM_PERIOD) && *n == '.' &&
1536                 (n == string || ((flags & FNM_PATHNAME) && n[-1] == '/')))
1537               return (FNM_NOMATCH);
1538
1539             /* Make sure there is a closing `]'.  If there isn't,
1540                the `[' is just a character to be matched.  */
1541             {
1542               register const char *np;
1543
1544               for (np = p; np && *np && *np != ']'; np++);
1545
1546               if (np && !*np)
1547                 {
1548                   if (*n != '[')
1549                     return (FNM_NOMATCH);
1550                   goto next_char;
1551                 }
1552             }
1553
1554             not = (*p == '!' || *p == '^');
1555             if (not)
1556               ++p;
1557
1558             c = *p++;
1559             while (1)
1560               {
1561                 register char cstart = c, cend = c;
1562
1563                 if (!(flags & FNM_NOESCAPE) && c == '\\')
1564                   cstart = cend = *p++;
1565
1566                 if (c == '\0')
1567                   /* [ (unterminated) loses.  */
1568                   return (FNM_NOMATCH);
1569
1570                 c = *p++;
1571
1572                 if ((flags & FNM_PATHNAME) && c == '/')
1573                   /* [/] can never match.  */
1574                   return (FNM_NOMATCH);
1575
1576                 if (c == '-' && *p != ']')
1577                   {
1578                     cend = *p++;
1579                     if (!(flags & FNM_NOESCAPE) && cend == '\\')
1580                       cend = *p++;
1581                     if (cend == '\0')
1582                       return (FNM_NOMATCH);
1583                     c = *p++;
1584                   }
1585
1586                 if (*n >= cstart && *n <= cend)
1587                   goto matched;
1588
1589                 if (c == ']')
1590                   break;
1591               }
1592             if (!not)
1593               return (FNM_NOMATCH);
1594
1595           next_char:
1596             break;
1597
1598           matched:
1599             /* Skip the rest of the [...] that already matched.  */
1600             while (c != ']')
1601               {
1602                 if (c == '\0')
1603                   /* [... (unterminated) loses.  */
1604                   return (FNM_NOMATCH);
1605
1606                 c = *p++;
1607                 if (!(flags & FNM_NOESCAPE) && c == '\\')
1608                   /* 1003.2d11 is unclear if this is right.  %%% */
1609                   ++p;
1610               }
1611             if (not)
1612               return (FNM_NOMATCH);
1613           }
1614           break;
1615
1616         default:
1617           if (c != *n)
1618             return (FNM_NOMATCH);
1619         }
1620
1621       ++n;
1622     }
1623
1624   if (*n == '\0')
1625     return (0);
1626
1627   return (FNM_NOMATCH);
1628 }
1629
1630 #endif /* not SYSTEM_FNMATCH */