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