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