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