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