]> sjero.net Git - wget/blob - src/cmpt.c
[svn] Rewrite parsing and handling of URLs.
[wget] / src / cmpt.c
1 /* Replacements for routines missing on some systems.
2    Copyright (C) 1995, 1996, 1997 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 #include <config.h>
21
22 #include <stdio.h>
23 #include <stdlib.h>
24 #ifdef HAVE_STRING_H
25 # include <string.h>
26 #else
27 # include <strings.h>
28 #endif /* HAVE_STRING_H */
29
30 #include <sys/types.h>
31 #ifdef HAVE_UNISTD_H
32 # include <unistd.h>
33 #endif
34 #include <limits.h>
35
36 #include "wget.h"
37
38 #ifndef HAVE_STRERROR
39 /* A strerror() clone, for systems that don't have it.  */
40 char *
41 strerror (int err)
42 {
43   /* This loses on a system without `sys_errlist'.  */
44   extern char *sys_errlist[];
45   return sys_errlist[err];
46 }
47 #endif /* not HAVE_STRERROR */
48
49 /* Some systems don't have some str* functions in libc.  Here we
50    define them.  The same goes for strptime.  */
51
52 #ifndef HAVE_STRCASECMP
53 /* From GNU libc.  */
54 /* Compare S1 and S2, ignoring case, returning less than, equal to or
55    greater than zero if S1 is lexiographically less than,
56    equal to or greater than S2.  */
57 int
58 strcasecmp (const char *s1, const char *s2)
59 {
60   register const unsigned char *p1 = (const unsigned char *) s1;
61   register const unsigned char *p2 = (const unsigned char *) s2;
62   unsigned char c1, c2;
63
64   if (p1 == p2)
65     return 0;
66
67   do
68     {
69       c1 = TOLOWER (*p1++);
70       c2 = TOLOWER (*p2++);
71       if (c1 == '\0')
72         break;
73     }
74   while (c1 == c2);
75
76   return c1 - c2;
77 }
78 #endif /* not HAVE_STRCASECMP */
79
80 #ifndef HAVE_STRNCASECMP
81 /* From GNU libc.  */
82 /* Compare no more than N characters of S1 and S2,
83    ignoring case, returning less than, equal to or
84    greater than zero if S1 is lexicographically less
85    than, equal to or greater than S2.  */
86 int
87 strncasecmp (const char *s1, const char *s2, size_t n)
88 {
89   register const unsigned char *p1 = (const unsigned char *) s1;
90   register const unsigned char *p2 = (const unsigned char *) s2;
91   unsigned char c1, c2;
92
93   if (p1 == p2 || n == 0)
94     return 0;
95
96   do
97     {
98       c1 = TOLOWER (*p1++);
99       c2 = TOLOWER (*p2++);
100       if (c1 == '\0' || c1 != c2)
101         return c1 - c2;
102     } while (--n > 0);
103
104   return c1 - c2;
105 }
106 #endif /* not HAVE_STRNCASECMP */
107
108 #ifndef HAVE_STRSTR
109 /* From GNU libc 2.0.6.  */
110 /* Return the first ocurrence of NEEDLE in HAYSTACK.  */
111 /*
112  * My personal strstr() implementation that beats most other algorithms.
113  * Until someone tells me otherwise, I assume that this is the
114  * fastest implementation of strstr() in C.
115  * I deliberately chose not to comment it.  You should have at least
116  * as much fun trying to understand it, as I had to write it :-).
117  *
118  * Stephen R. van den Berg, berg@pool.informatik.rwth-aachen.de */
119 typedef unsigned chartype;
120
121 char *
122 strstr (phaystack, pneedle)
123      const char *phaystack;
124      const char *pneedle;
125 {
126   register const unsigned char *haystack, *needle;
127   register chartype b, c;
128
129   haystack = (const unsigned char *) phaystack;
130   needle = (const unsigned char *) pneedle;
131
132   b = *needle;
133   if (b != '\0')
134     {
135       haystack--;                               /* possible ANSI violation */
136       do
137         {
138           c = *++haystack;
139           if (c == '\0')
140             goto ret0;
141         }
142       while (c != b);
143
144       c = *++needle;
145       if (c == '\0')
146         goto foundneedle;
147       ++needle;
148       goto jin;
149
150       for (;;)
151         {
152           register chartype a;
153           register const unsigned char *rhaystack, *rneedle;
154
155           do
156             {
157               a = *++haystack;
158               if (a == '\0')
159                 goto ret0;
160               if (a == b)
161                 break;
162               a = *++haystack;
163               if (a == '\0')
164                 goto ret0;
165 shloop:     }
166           while (a != b);
167
168 jin:      a = *++haystack;
169           if (a == '\0')
170             goto ret0;
171
172           if (a != c)
173             goto shloop;
174
175           rhaystack = haystack-- + 1;
176           rneedle = needle;
177           a = *rneedle;
178
179           if (*rhaystack == a)
180             do
181               {
182                 if (a == '\0')
183                   goto foundneedle;
184                 ++rhaystack;
185                 a = *++needle;
186                 if (*rhaystack != a)
187                   break;
188                 if (a == '\0')
189                   goto foundneedle;
190                 ++rhaystack;
191                 a = *++needle;
192               }
193             while (*rhaystack == a);
194
195           needle = rneedle;             /* took the register-poor approach */
196
197           if (a == '\0')
198             break;
199         }
200     }
201 foundneedle:
202   return (char*) haystack;
203 ret0:
204   return 0;
205 }
206 #endif /* not HAVE_STRSTR */
207
208 #ifndef HAVE_STRPBRK
209 /* Find the first ocurrence in S of any character in ACCEPT.  */
210 char *
211 strpbrk (const char *s, const char *accept)
212 {
213   while (*s != '\0')
214     {
215       const char *a = accept;
216       while (*a != '\0')
217         if (*a++ == *s)
218           return (char *) s;
219       ++s;
220     }
221
222   return 0;
223 }
224 #endif /* HAVE_STRPBRK */
225
226 #ifndef HAVE_MKTIME
227 /* From GNU libc 2.0.  */
228
229 /* Copyright (C) 1993, 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
230    This file is part of the GNU C Library.
231    Contributed by Paul Eggert (eggert@twinsun.com).  */
232
233 #ifdef _LIBC
234 # define HAVE_LIMITS_H 1
235 # define HAVE_LOCALTIME_R 1
236 # define STDC_HEADERS 1
237 #endif
238
239 /* Assume that leap seconds are possible, unless told otherwise.
240    If the host has a `zic' command with a `-L leapsecondfilename' option,
241    then it supports leap seconds; otherwise it probably doesn't.  */
242 #ifndef LEAP_SECONDS_POSSIBLE
243 # define LEAP_SECONDS_POSSIBLE 1
244 #endif
245
246 #ifndef __P
247 # define __P(args) PARAMS (args)
248 #endif  /* Not __P.  */
249
250 #ifndef CHAR_BIT
251 # define CHAR_BIT 8
252 #endif
253
254 #ifndef INT_MIN
255 # define INT_MIN (~0 << (sizeof (int) * CHAR_BIT - 1))
256 #endif
257 #ifndef INT_MAX
258 # define INT_MAX (~0 - INT_MIN)
259 #endif
260
261 #ifndef TIME_T_MIN
262 /* The outer cast to time_t works around a bug in Cray C 5.0.3.0.  */
263 # define TIME_T_MIN ((time_t) \
264                     (0 < (time_t) -1 ? (time_t) 0 \
265                      : ~ (time_t) 0 << (sizeof (time_t) * CHAR_BIT - 1)))
266 #endif
267 #ifndef TIME_T_MAX
268 # define TIME_T_MAX (~ (time_t) 0 - TIME_T_MIN)
269 #endif
270
271 #define TM_YEAR_BASE 1900
272 #define EPOCH_YEAR 1970
273
274 #ifndef __isleap
275 /* Nonzero if YEAR is a leap year (every 4 years,
276    except every 100th isn't, and every 400th is).  */
277 # define __isleap(year) \
278   ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
279 #endif
280
281 /* How many days come before each month (0-12).  */
282 const unsigned short int __mon_yday[2][13] =
283   {
284     /* Normal years.  */
285     { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
286     /* Leap years.  */
287     { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
288   };
289
290 static time_t ydhms_tm_diff __P ((int, int, int, int, int, const struct tm *));
291 time_t __mktime_internal __P ((struct tm *,
292                                struct tm *(*) (const time_t *, struct tm *),
293                                time_t *));
294
295
296 #ifdef _LIBC
297 # define localtime_r __localtime_r
298 #else
299 # if ! HAVE_LOCALTIME_R && ! defined localtime_r
300 /* Approximate localtime_r as best we can in its absence.  */
301 #  define localtime_r my_mktime_localtime_r
302 static struct tm *localtime_r __P ((const time_t *, struct tm *));
303 static struct tm *
304 localtime_r (t, tp)
305      const time_t *t;
306      struct tm *tp;
307 {
308   struct tm *l = localtime (t);
309   if (! l)
310     return 0;
311   *tp = *l;
312   return tp;
313 }
314 # endif /* ! HAVE_LOCALTIME_R && ! defined (localtime_r) */
315 #endif /* ! _LIBC */
316
317
318 /* Yield the difference between (YEAR-YDAY HOUR:MIN:SEC) and (*TP),
319    measured in seconds, ignoring leap seconds.
320    YEAR uses the same numbering as TM->tm_year.
321    All values are in range, except possibly YEAR.
322    If overflow occurs, yield the low order bits of the correct answer.  */
323 static time_t
324 ydhms_tm_diff (year, yday, hour, min, sec, tp)
325      int year, yday, hour, min, sec;
326      const struct tm *tp;
327 {
328   /* Compute intervening leap days correctly even if year is negative.
329      Take care to avoid int overflow.  time_t overflow is OK, since
330      only the low order bits of the correct time_t answer are needed.
331      Don't convert to time_t until after all divisions are done, since
332      time_t might be unsigned.  */
333   int a4 = (year >> 2) + (TM_YEAR_BASE >> 2) - ! (year & 3);
334   int b4 = (tp->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (tp->tm_year & 3);
335   int a100 = a4 / 25 - (a4 % 25 < 0);
336   int b100 = b4 / 25 - (b4 % 25 < 0);
337   int a400 = a100 >> 2;
338   int b400 = b100 >> 2;
339   int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
340   time_t years = year - (time_t) tp->tm_year;
341   time_t days = (365 * years + intervening_leap_days
342                  + (yday - tp->tm_yday));
343   return (60 * (60 * (24 * days + (hour - tp->tm_hour))
344                 + (min - tp->tm_min))
345           + (sec - tp->tm_sec));
346 }
347
348
349 static time_t localtime_offset;
350
351 /* Convert *TP to a time_t value.  */
352 time_t
353 mktime (tp)
354      struct tm *tp;
355 {
356 #ifdef _LIBC
357   /* POSIX.1 8.1.1 requires that whenever mktime() is called, the
358      time zone names contained in the external variable `tzname' shall
359      be set as if the tzset() function had been called.  */
360   __tzset ();
361 #endif
362
363   return __mktime_internal (tp, localtime_r, &localtime_offset);
364 }
365
366 /* Convert *TP to a time_t value, inverting
367    the monotonic and mostly-unit-linear conversion function CONVERT.
368    Use *OFFSET to keep track of a guess at the offset of the result,
369    compared to what the result would be for UTC without leap seconds.
370    If *OFFSET's guess is correct, only one CONVERT call is needed.  */
371 time_t
372 __mktime_internal (tp, convert, offset)
373      struct tm *tp;
374      struct tm *(*convert) __P ((const time_t *, struct tm *));
375      time_t *offset;
376 {
377   time_t t, dt, t0;
378   struct tm tm;
379
380   /* The maximum number of probes (calls to CONVERT) should be enough
381      to handle any combinations of time zone rule changes, solar time,
382      and leap seconds.  Posix.1 prohibits leap seconds, but some hosts
383      have them anyway.  */
384   int remaining_probes = 4;
385
386   /* Time requested.  Copy it in case CONVERT modifies *TP; this can
387      occur if TP is localtime's returned value and CONVERT is localtime.  */
388   int sec = tp->tm_sec;
389   int min = tp->tm_min;
390   int hour = tp->tm_hour;
391   int mday = tp->tm_mday;
392   int mon = tp->tm_mon;
393   int year_requested = tp->tm_year;
394   int isdst = tp->tm_isdst;
395
396   /* Ensure that mon is in range, and set year accordingly.  */
397   int mon_remainder = mon % 12;
398   int negative_mon_remainder = mon_remainder < 0;
399   int mon_years = mon / 12 - negative_mon_remainder;
400   int year = year_requested + mon_years;
401
402   /* The other values need not be in range:
403      the remaining code handles minor overflows correctly,
404      assuming int and time_t arithmetic wraps around.
405      Major overflows are caught at the end.  */
406
407   /* Calculate day of year from year, month, and day of month.
408      The result need not be in range.  */
409   int yday = ((__mon_yday[__isleap (year + TM_YEAR_BASE)]
410                [mon_remainder + 12 * negative_mon_remainder])
411               + mday - 1);
412
413   int sec_requested = sec;
414 #if LEAP_SECONDS_POSSIBLE
415   /* Handle out-of-range seconds specially,
416      since ydhms_tm_diff assumes every minute has 60 seconds.  */
417   if (sec < 0)
418     sec = 0;
419   if (59 < sec)
420     sec = 59;
421 #endif
422
423   /* Invert CONVERT by probing.  First assume the same offset as last time.
424      Then repeatedly use the error to improve the guess.  */
425
426   tm.tm_year = EPOCH_YEAR - TM_YEAR_BASE;
427   tm.tm_yday = tm.tm_hour = tm.tm_min = tm.tm_sec = 0;
428   t0 = ydhms_tm_diff (year, yday, hour, min, sec, &tm);
429
430   for (t = t0 + *offset;
431        (dt = ydhms_tm_diff (year, yday, hour, min, sec, (*convert) (&t, &tm)));
432        t += dt)
433     if (--remaining_probes == 0)
434       return -1;
435
436   /* Check whether tm.tm_isdst has the requested value, if any.  */
437   if (0 <= isdst && 0 <= tm.tm_isdst)
438     {
439       int dst_diff = (isdst != 0) - (tm.tm_isdst != 0);
440       if (dst_diff)
441         {
442           /* Move two hours in the direction indicated by the disagreement,
443              probe some more, and switch to a new time if found.
444              The largest known fallback due to daylight savings is two hours:
445              once, in Newfoundland, 1988-10-30 02:00 -> 00:00.  */
446           time_t ot = t - 2 * 60 * 60 * dst_diff;
447           while (--remaining_probes != 0)
448             {
449               struct tm otm;
450               if (! (dt = ydhms_tm_diff (year, yday, hour, min, sec,
451                                          (*convert) (&ot, &otm))))
452                 {
453                   t = ot;
454                   tm = otm;
455                   break;
456                 }
457               if ((ot += dt) == t)
458                 break;  /* Avoid a redundant probe.  */
459             }
460         }
461     }
462
463   *offset = t - t0;
464
465 #if LEAP_SECONDS_POSSIBLE
466   if (sec_requested != tm.tm_sec)
467     {
468       /* Adjust time to reflect the tm_sec requested, not the normalized value.
469          Also, repair any damage from a false match due to a leap second.  */
470       t += sec_requested - sec + (sec == 0 && tm.tm_sec == 60);
471       (*convert) (&t, &tm);
472     }
473 #endif
474
475   if (TIME_T_MAX / INT_MAX / 366 / 24 / 60 / 60 < 3)
476     {
477       /* time_t isn't large enough to rule out overflows in ydhms_tm_diff,
478          so check for major overflows.  A gross check suffices,
479          since if t has overflowed, it is off by a multiple of
480          TIME_T_MAX - TIME_T_MIN + 1.  So ignore any component of
481          the difference that is bounded by a small value.  */
482
483       double dyear = (double) year_requested + mon_years - tm.tm_year;
484       double dday = 366 * dyear + mday;
485       double dsec = 60 * (60 * (24 * dday + hour) + min) + sec_requested;
486
487       if (TIME_T_MAX / 3 - TIME_T_MIN / 3 < (dsec < 0 ? - dsec : dsec))
488         return -1;
489     }
490
491   *tp = tm;
492   return t;
493 }
494
495 #ifdef weak_alias
496 weak_alias (mktime, timelocal)
497 #endif
498 #endif /* not HAVE_MKTIME */
499
500
501 #ifndef HAVE_STRPTIME
502 /* From GNU libc 2.0.6.  */
503 /* Ulrich, thanks for helping me out with this!  --hniksic  */
504
505 /* strptime - Convert a string representation of time to a time value.
506    Copyright (C) 1996, 1997 Free Software Foundation, Inc.
507    This file is part of the GNU C Library.
508    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.  */
509
510 /* XXX This version of the implementation is not really complete.
511    Some of the fields cannot add information alone.  But if seeing
512    some of them in the same format (such as year, week and weekday)
513    this is enough information for determining the date.  */
514
515 #ifndef __P
516 # define __P(args) PARAMS (args)
517 #endif /* not __P */
518
519 #if ! HAVE_LOCALTIME_R && ! defined (localtime_r)
520 #ifdef _LIBC
521 #define localtime_r __localtime_r
522 #else
523 /* Approximate localtime_r as best we can in its absence.  */
524 #define localtime_r my_localtime_r
525 static struct tm *localtime_r __P ((const time_t *, struct tm *));
526 static struct tm *
527 localtime_r (t, tp)
528      const time_t *t;
529      struct tm *tp;
530 {
531   struct tm *l = localtime (t);
532   if (! l)
533     return 0;
534   *tp = *l;
535   return tp;
536 }
537 #endif /* ! _LIBC */
538 #endif /* ! HAVE_LOCALTIME_R && ! defined (localtime_r) */
539
540
541 #define match_char(ch1, ch2) if (ch1 != ch2) return NULL
542 #if defined __GNUC__ && __GNUC__ >= 2
543 # define match_string(cs1, s2) \
544   ({ size_t len = strlen (cs1);                                               \
545      int result = strncasecmp ((cs1), (s2), len) == 0;                        \
546      if (result) (s2) += len;                                                 \
547      result; })
548 #else
549 /* Oh come on.  Get a reasonable compiler.  */
550 # define match_string(cs1, s2) \
551   (strncasecmp ((cs1), (s2), strlen (cs1)) ? 0 : ((s2) += strlen (cs1), 1))
552 #endif
553 /* We intentionally do not use isdigit() for testing because this will
554    lead to problems with the wide character version.  */
555 #define get_number(from, to) \
556   do {                                                                        \
557     val = 0;                                                                  \
558     if (*rp < '0' || *rp > '9')                                               \
559       return NULL;                                                            \
560     do {                                                                      \
561       val *= 10;                                                              \
562       val += *rp++ - '0';                                                     \
563     } while (val * 10 <= to && *rp >= '0' && *rp <= '9');                     \
564     if (val < from || val > to)                                               \
565       return NULL;                                                            \
566   } while (0)
567 #ifdef _NL_CURRENT
568 # define get_alt_number(from, to) \
569   do {                                                                        \
570     if (*decided != raw)                                                      \
571       {                                                                       \
572         const char *alts = _NL_CURRENT (LC_TIME, ALT_DIGITS);                 \
573         val = 0;                                                              \
574         while (*alts != '\0')                                                 \
575           {                                                                   \
576             size_t len = strlen (alts);                                       \
577             if (strncasecmp (alts, rp, len) == 0)                             \
578               break;                                                          \
579             alts = strchr (alts, '\0') + 1;                                   \
580             ++val;                                                            \
581           }                                                                   \
582         if (*alts == '\0')                                                    \
583           {                                                                   \
584             if (*decided == loc && val != 0)                                  \
585               return NULL;                                                    \
586           }                                                                   \
587         else                                                                  \
588           {                                                                   \
589             *decided = loc;                                                   \
590             break;                                                            \
591           }                                                                   \
592       }                                                                       \
593     get_number (from, to);                                                    \
594   } while (0)
595 #else
596 # define get_alt_number(from, to) \
597   /* We don't have the alternate representation.  */                          \
598   get_number(from, to)
599 #endif
600 #define recursive(new_fmt) \
601   (*(new_fmt) != '\0'                                                         \
602    && (rp = strptime_internal (rp, (new_fmt), tm, decided)) != NULL)
603
604
605 #ifdef _LIBC
606 /* This is defined in locale/C-time.c in the GNU libc.  */
607 extern const struct locale_data _nl_C_LC_TIME;
608
609 # define weekday_name (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (DAY_1)].string)
610 # define ab_weekday_name \
611   (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (ABDAY_1)].string)
612 # define month_name (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (MON_1)].string)
613 # define ab_month_name (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (ABMON_1)].string)
614 # define HERE_D_T_FMT (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (D_T_FMT)].string)
615 # define HERE_D_FMT (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (D_T_FMT)].string)
616 # define HERE_AM_STR (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (AM_STR)].string)
617 # define HERE_PM_STR (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (PM_STR)].string)
618 # define HERE_T_FMT_AMPM \
619   (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (T_FMT_AMPM)].string)
620 # define HERE_T_FMT (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (T_FMT)].string)
621 #else
622 static char const weekday_name[][10] =
623   {
624     "Sunday", "Monday", "Tuesday", "Wednesday",
625     "Thursday", "Friday", "Saturday"
626   };
627 static char const ab_weekday_name[][4] =
628   {
629     "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
630   };
631 static char const month_name[][10] =
632   {
633     "January", "February", "March", "April", "May", "June",
634     "July", "August", "September", "October", "November", "December"
635   };
636 static char const ab_month_name[][4] =
637   {
638     "Jan", "Feb", "Mar", "Apr", "May", "Jun",
639     "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
640   };
641 # define HERE_D_T_FMT "%a %b %e %H:%M:%S %Y"
642 # define HERE_D_FMT "%m/%d/%y"
643 # define HERE_AM_STR "AM"
644 # define HERE_PM_STR "PM"
645 # define HERE_T_FMT_AMPM "%I:%M:%S %p"
646 # define HERE_T_FMT "%H:%M:%S"
647 #endif
648
649 /* Status of lookup: do we use the locale data or the raw data?  */
650 enum locale_status { not, loc, raw };
651
652 static char *
653 strptime_internal __P ((const char *buf, const char *format, struct tm *tm,
654                         enum locale_status *decided));
655
656 static char *
657 strptime_internal (buf, format, tm, decided)
658      const char *buf;
659      const char *format;
660      struct tm *tm;
661      enum locale_status *decided;
662 {
663   const char *rp;
664   const char *fmt;
665   int cnt;
666   size_t val;
667   int have_I, is_pm;
668
669   rp = buf;
670   fmt = format;
671   have_I = is_pm = 0;
672
673   while (*fmt != '\0')
674     {
675       /* A white space in the format string matches 0 more or white
676          space in the input string.  */
677       if (ISSPACE (*fmt))
678         {
679           while (ISSPACE (*rp))
680             ++rp;
681           ++fmt;
682           continue;
683         }
684
685       /* Any character but `%' must be matched by the same character
686          in the iput string.  */
687       if (*fmt != '%')
688         {
689           match_char (*fmt++, *rp++);
690           continue;
691         }
692
693       ++fmt;
694 #ifndef _NL_CURRENT
695       /* We need this for handling the `E' modifier.  */
696     start_over:
697 #endif
698       switch (*fmt++)
699         {
700         case '%':
701           /* Match the `%' character itself.  */
702           match_char ('%', *rp++);
703           break;
704         case 'a':
705         case 'A':
706           /* Match day of week.  */
707           for (cnt = 0; cnt < 7; ++cnt)
708             {
709 #ifdef _NL_CURRENT
710               if (*decided !=raw)
711                 {
712                   if (match_string (_NL_CURRENT (LC_TIME, DAY_1 + cnt), rp))
713                     {
714                       if (*decided == not
715                           && strcmp (_NL_CURRENT (LC_TIME, DAY_1 + cnt),
716                                      weekday_name[cnt]))
717                         *decided = loc;
718                       break;
719                     }
720                   if (match_string (_NL_CURRENT (LC_TIME, ABDAY_1 + cnt), rp))
721                     {
722                       if (*decided == not
723                           && strcmp (_NL_CURRENT (LC_TIME, ABDAY_1 + cnt),
724                                      ab_weekday_name[cnt]))
725                         *decided = loc;
726                       break;
727                     }
728                 }
729 #endif
730               if (*decided != loc
731                   && (match_string (weekday_name[cnt], rp)
732                       || match_string (ab_weekday_name[cnt], rp)))
733                 {
734                   *decided = raw;
735                   break;
736                 }
737             }
738           if (cnt == 7)
739             /* Does not match a weekday name.  */
740             return NULL;
741           tm->tm_wday = cnt;
742           break;
743         case 'b':
744         case 'B':
745         case 'h':
746           /* Match month name.  */
747           for (cnt = 0; cnt < 12; ++cnt)
748             {
749 #ifdef _NL_CURRENT
750               if (*decided !=raw)
751                 {
752                   if (match_string (_NL_CURRENT (LC_TIME, MON_1 + cnt), rp))
753                     {
754                       if (*decided == not
755                           && strcmp (_NL_CURRENT (LC_TIME, MON_1 + cnt),
756                                      month_name[cnt]))
757                         *decided = loc;
758                       break;
759                     }
760                   if (match_string (_NL_CURRENT (LC_TIME, ABMON_1 + cnt), rp))
761                     {
762                       if (*decided == not
763                           && strcmp (_NL_CURRENT (LC_TIME, ABMON_1 + cnt),
764                                      ab_month_name[cnt]))
765                         *decided = loc;
766                       break;
767                     }
768                 }
769 #endif
770               if (match_string (month_name[cnt], rp)
771                   || match_string (ab_month_name[cnt], rp))
772                 {
773                   *decided = raw;
774                   break;
775                 }
776             }
777           if (cnt == 12)
778             /* Does not match a month name.  */
779             return NULL;
780           tm->tm_mon = cnt;
781           break;
782         case 'c':
783           /* Match locale's date and time format.  */
784 #ifdef _NL_CURRENT
785           if (*decided != raw)
786             {
787               if (!recursive (_NL_CURRENT (LC_TIME, D_T_FMT)))
788                 {
789                   if (*decided == loc)
790                     return NULL;
791                 }
792               else
793                 {
794                   if (*decided == not &&
795                       strcmp (_NL_CURRENT (LC_TIME, D_T_FMT), HERE_D_T_FMT))
796                     *decided = loc;
797                   break;
798                 }
799               *decided = raw;
800             }
801 #endif
802           if (!recursive (HERE_D_T_FMT))
803             return NULL;
804           break;
805         case 'C':
806           /* Match century number.  */
807           get_number (0, 99);
808           /* We don't need the number.  */
809           break;
810         case 'd':
811         case 'e':
812           /* Match day of month.  */
813           get_number (1, 31);
814           tm->tm_mday = val;
815           break;
816         case 'x':
817 #ifdef _NL_CURRENT
818           if (*decided != raw)
819             {
820               if (!recursive (_NL_CURRENT (LC_TIME, D_FMT)))
821                 {
822                   if (*decided == loc)
823                     return NULL;
824                 }
825               else
826                 {
827                   if (decided == not
828                       && strcmp (_NL_CURRENT (LC_TIME, D_FMT), HERE_D_FMT))
829                     *decided = loc;
830                   break;
831                 }
832               *decided = raw;
833             }
834 #endif
835           /* Fall through.  */
836         case 'D':
837           /* Match standard day format.  */
838           if (!recursive (HERE_D_FMT))
839             return NULL;
840           break;
841         case 'H':
842           /* Match hour in 24-hour clock.  */
843           get_number (0, 23);
844           tm->tm_hour = val;
845           have_I = 0;
846           break;
847         case 'I':
848           /* Match hour in 12-hour clock.  */
849           get_number (1, 12);
850           tm->tm_hour = val % 12;
851           have_I = 1;
852           break;
853         case 'j':
854           /* Match day number of year.  */
855           get_number (1, 366);
856           tm->tm_yday = val - 1;
857           break;
858         case 'm':
859           /* Match number of month.  */
860           get_number (1, 12);
861           tm->tm_mon = val - 1;
862           break;
863         case 'M':
864           /* Match minute.  */
865           get_number (0, 59);
866           tm->tm_min = val;
867           break;
868         case 'n':
869         case 't':
870           /* Match any white space.  */
871           while (ISSPACE (*rp))
872             ++rp;
873           break;
874         case 'p':
875           /* Match locale's equivalent of AM/PM.  */
876 #ifdef _NL_CURRENT
877           if (*decided != raw)
878             {
879               if (match_string (_NL_CURRENT (LC_TIME, AM_STR), rp))
880                 {
881                   if (strcmp (_NL_CURRENT (LC_TIME, AM_STR), HERE_AM_STR))
882                     *decided = loc;
883                   break;
884                 }
885               if (match_string (_NL_CURRENT (LC_TIME, PM_STR), rp))
886                 {
887                   if (strcmp (_NL_CURRENT (LC_TIME, PM_STR), HERE_PM_STR))
888                     *decided = loc;
889                   is_pm = 1;
890                   break;
891                 }
892               *decided = raw;
893             }
894 #endif
895           if (!match_string (HERE_AM_STR, rp))
896             if (match_string (HERE_PM_STR, rp))
897               is_pm = 1;
898             else
899               return NULL;
900           break;
901         case 'r':
902 #ifdef _NL_CURRENT
903           if (*decided != raw)
904             {
905               if (!recursive (_NL_CURRENT (LC_TIME, T_FMT_AMPM)))
906                 {
907                   if (*decided == loc)
908                     return NULL;
909                 }
910               else
911                 {
912                   if (*decided == not &&
913                       strcmp (_NL_CURRENT (LC_TIME, T_FMT_AMPM),
914                               HERE_T_FMT_AMPM))
915                     *decided = loc;
916                   break;
917                 }
918               *decided = raw;
919             }
920 #endif
921           if (!recursive (HERE_T_FMT_AMPM))
922             return NULL;
923           break;
924         case 'R':
925           if (!recursive ("%H:%M"))
926             return NULL;
927           break;
928         case 's':
929           {
930             /* The number of seconds may be very high so we cannot use
931                the `get_number' macro.  Instead read the number
932                character for character and construct the result while
933                doing this.  */
934             time_t secs;
935             if (*rp < '0' || *rp > '9')
936               /* We need at least one digit.  */
937               return NULL;
938
939             do
940               {
941                 secs *= 10;
942                 secs += *rp++ - '0';
943               }
944             while (*rp >= '0' && *rp <= '9');
945
946             if (localtime_r (&secs, tm) == NULL)
947               /* Error in function.  */
948               return NULL;
949           }
950           break;
951         case 'S':
952           get_number (0, 61);
953           tm->tm_sec = val;
954           break;
955         case 'X':
956 #ifdef _NL_CURRENT
957           if (*decided != raw)
958             {
959               if (!recursive (_NL_CURRENT (LC_TIME, T_FMT)))
960                 {
961                   if (*decided == loc)
962                     return NULL;
963                 }
964               else
965                 {
966                   if (strcmp (_NL_CURRENT (LC_TIME, T_FMT), HERE_T_FMT))
967                     *decided = loc;
968                   break;
969                 }
970               *decided = raw;
971             }
972 #endif
973           /* Fall through.  */
974         case 'T':
975           if (!recursive (HERE_T_FMT))
976             return NULL;
977           break;
978         case 'u':
979           get_number (1, 7);
980           tm->tm_wday = val % 7;
981           break;
982         case 'g':
983           get_number (0, 99);
984           /* XXX This cannot determine any field in TM.  */
985           break;
986         case 'G':
987           if (*rp < '0' || *rp > '9')
988             return NULL;
989           /* XXX Ignore the number since we would need some more
990              information to compute a real date.  */
991           do
992             ++rp;
993           while (*rp >= '0' && *rp <= '9');
994           break;
995         case 'U':
996         case 'V':
997         case 'W':
998           get_number (0, 53);
999           /* XXX This cannot determine any field in TM without some
1000              information.  */
1001           break;
1002         case 'w':
1003           /* Match number of weekday.  */
1004           get_number (0, 6);
1005           tm->tm_wday = val;
1006           break;
1007         case 'y':
1008           /* Match year within century.  */
1009           get_number (0, 99);
1010           tm->tm_year = val >= 50 ? val : val + 100;
1011           break;
1012         case 'Y':
1013           /* Match year including century number.  */
1014           if (sizeof (time_t) > 4)
1015             get_number (0, 9999);
1016           else
1017             get_number (0, 2036);
1018           tm->tm_year = val - 1900;
1019           break;
1020         case 'Z':
1021           /* XXX How to handle this?  */
1022           break;
1023         case 'E':
1024 #ifdef _NL_CURRENT
1025           switch (*fmt++)
1026             {
1027             case 'c':
1028               /* Match locale's alternate date and time format.  */
1029               if (*decided != raw)
1030                 {
1031                   const char *fmt = _NL_CURRENT (LC_TIME, ERA_D_T_FMT);
1032
1033                   if (*fmt == '\0')
1034                     fmt = _NL_CURRENT (LC_TIME, D_T_FMT);
1035
1036                   if (!recursive (fmt))
1037                     {
1038                       if (*decided == loc)
1039                         return NULL;
1040                     }
1041                   else
1042                     {
1043                       if (strcmp (fmt, HERE_D_T_FMT))
1044                         *decided = loc;
1045                       break;
1046                     }
1047                   *decided = raw;
1048                 }
1049               /* The C locale has no era information, so use the
1050                  normal representation.  */
1051               if (!recursive (HERE_D_T_FMT))
1052                 return NULL;
1053               break;
1054             case 'C':
1055             case 'y':
1056             case 'Y':
1057               /* Match name of base year in locale's alternate
1058                  representation.  */
1059               /* XXX This is currently not implemented.  It should
1060                  use the value _NL_CURRENT (LC_TIME, ERA).  */
1061               break;
1062             case 'x':
1063               if (*decided != raw)
1064                 {
1065                   const char *fmt = _NL_CURRENT (LC_TIME, ERA_D_FMT);
1066
1067                   if (*fmt == '\0')
1068                     fmt = _NL_CURRENT (LC_TIME, D_FMT);
1069
1070                   if (!recursive (fmt))
1071                     {
1072                       if (*decided == loc)
1073                         return NULL;
1074                     }
1075                   else
1076                     {
1077                       if (strcmp (fmt, HERE_D_FMT))
1078                         *decided = loc;
1079                       break;
1080                     }
1081                   *decided = raw;
1082                 }
1083               if (!recursive (HERE_D_FMT))
1084                 return NULL;
1085               break;
1086             case 'X':
1087               if (*decided != raw)
1088                 {
1089                   const char *fmt = _NL_CURRENT (LC_TIME, ERA_T_FMT);
1090
1091                   if (*fmt == '\0')
1092                     fmt = _NL_CURRENT (LC_TIME, T_FMT);
1093
1094                   if (!recursive (fmt))
1095                     {
1096                       if (*decided == loc)
1097                         return NULL;
1098                     }
1099                   else
1100                     {
1101                       if (strcmp (fmt, HERE_T_FMT))
1102                         *decided = loc;
1103                       break;
1104                     }
1105                   *decided = raw;
1106                 }
1107               if (!recursive (HERE_T_FMT))
1108                 return NULL;
1109               break;
1110             default:
1111               return NULL;
1112             }
1113           break;
1114 #else
1115           /* We have no information about the era format.  Just use
1116              the normal format.  */
1117           if (*fmt != 'c' && *fmt != 'C' && *fmt != 'y' && *fmt != 'Y'
1118               && *fmt != 'x' && *fmt != 'X')
1119             /* This is an illegal format.  */
1120             return NULL;
1121
1122           goto start_over;
1123 #endif
1124         case 'O':
1125           switch (*fmt++)
1126             {
1127             case 'd':
1128             case 'e':
1129               /* Match day of month using alternate numeric symbols.  */
1130               get_alt_number (1, 31);
1131               tm->tm_mday = val;
1132               break;
1133             case 'H':
1134               /* Match hour in 24-hour clock using alternate numeric
1135                  symbols.  */
1136               get_alt_number (0, 23);
1137               tm->tm_hour = val;
1138               have_I = 0;
1139               break;
1140             case 'I':
1141               /* Match hour in 12-hour clock using alternate numeric
1142                  symbols.  */
1143               get_alt_number (1, 12);
1144               tm->tm_hour = val - 1;
1145               have_I = 1;
1146               break;
1147             case 'm':
1148               /* Match month using alternate numeric symbols.  */
1149               get_alt_number (1, 12);
1150               tm->tm_mon = val - 1;
1151               break;
1152             case 'M':
1153               /* Match minutes using alternate numeric symbols.  */
1154               get_alt_number (0, 59);
1155               tm->tm_min = val;
1156               break;
1157             case 'S':
1158               /* Match seconds using alternate numeric symbols.  */
1159               get_alt_number (0, 61);
1160               tm->tm_sec = val;
1161               break;
1162             case 'U':
1163             case 'V':
1164             case 'W':
1165               get_alt_number (0, 53);
1166               /* XXX This cannot determine any field in TM without
1167                  further information.  */
1168               break;
1169             case 'w':
1170               /* Match number of weekday using alternate numeric symbols.  */
1171               get_alt_number (0, 6);
1172               tm->tm_wday = val;
1173               break;
1174             case 'y':
1175               /* Match year within century using alternate numeric symbols.  */
1176               get_alt_number (0, 99);
1177               break;
1178             default:
1179               return NULL;
1180             }
1181           break;
1182         default:
1183           return NULL;
1184         }
1185     }
1186
1187   if (have_I && is_pm)
1188     tm->tm_hour += 12;
1189
1190   return (char *) rp;
1191 }
1192
1193
1194 char *
1195 strptime (buf, format, tm)
1196      const char *buf;
1197      const char *format;
1198      struct tm *tm;
1199 {
1200   enum locale_status decided;
1201 #ifdef _NL_CURRENT
1202   decided = not;
1203 #else
1204   decided = raw;
1205 #endif
1206   return strptime_internal (buf, format, tm, &decided);
1207 }
1208 #endif /* not HAVE_STRPTIME */