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