#include <stdio.h>
#include <stdlib.h>
-#ifdef HAVE_STRING_H
-# include <string.h>
-#else /* not HAVE_STRING_H */
-# include <strings.h>
-#endif /* not HAVE_STRING_H */
-#include <sys/types.h>
+#include <string.h>
+#include <time.h>
+#ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+#endif
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#ifdef HAVE_PWD_H
# include <pwd.h>
#endif
-#ifdef HAVE_LIMITS_H
-# include <limits.h>
-#endif
#ifdef HAVE_UTIME_H
# include <utime.h>
#endif
#endif
#include <fcntl.h>
#include <assert.h>
-#ifdef WGET_USE_STDARG
-# include <stdarg.h>
-#else
-# include <varargs.h>
-#endif
+#include <stdarg.h>
/* For TIOCGWINSZ and friends: */
#ifdef HAVE_SYS_IOCTL_H
#endif
/* Needed for run_with_timeout. */
-#undef USE_SIGNAL_TIMEOUT
-#ifdef HAVE_SIGNAL_H
-# include <signal.h>
-#endif
+#include <signal.h>
#ifdef HAVE_SETJMP_H
# include <setjmp.h>
#endif
# endif
#endif
+#undef USE_SIGNAL_TIMEOUT
#ifdef HAVE_SIGNAL
-# ifdef HAVE_SIGSETJMP
-# define USE_SIGNAL_TIMEOUT
-# endif
-# ifdef HAVE_SIGBLOCK
+# if defined(HAVE_SIGSETJMP) || defined(HAVE_SIGBLOCK)
# define USE_SIGNAL_TIMEOUT
# endif
#endif
#include "utils.h"
#include "hash.h"
-#ifndef errno
-extern int errno;
-#endif
-
/* Utility function: like xstrdup(), but also lowercases S. */
char *
char *
strdupdelim (const char *beg, const char *end)
{
- char *res = (char *)xmalloc (end - beg + 1);
+ char *res = xmalloc (end - beg + 1);
memcpy (res, beg, end - beg);
res[end - beg] = '\0';
return res;
{
if (*s == ',')
{
- res = (char **)xrealloc (res, (i + 2) * sizeof (char *));
+ res = xrealloc (res, (i + 2) * sizeof (char *));
res[i] = strdupdelim (p, s);
res[++i] = NULL;
++s;
else
++s;
}
- res = (char **)xrealloc (res, (i + 2) * sizeof (char *));
+ res = xrealloc (res, (i + 2) * sizeof (char *));
res[i] = strdupdelim (p, s);
res[i + 1] = NULL;
return res;
}
\f
-#ifdef WGET_USE_STDARG
-# define VA_START(args, arg1) va_start (args, arg1)
-#else
-# define VA_START(args, ignored) va_start (args)
-#endif
-
/* Like sprintf, but allocates a string of sufficient size with malloc
and returns it. GNU libc has a similar function named asprintf,
which requires the pointer to the string to be passed. */
/* See log_vprintf_internal for explanation why it's OK to rely
on the return value of vsnprintf. */
- VA_START (args, fmt);
+ va_start (args, fmt);
n = vsnprintf (str, size, fmt, args);
va_end (args);
size <<= 1; /* twice the old size */
str = xrealloc (str, size);
}
- return NULL; /* unreached */
}
/* Concatenate the NULL-terminated list of string arguments into
/* Calculate the length of and allocate the resulting string. */
argcount = 0;
- VA_START (args, str0);
+ va_start (args, str0);
for (next_str = str0; next_str != NULL; next_str = va_arg (args, char *))
{
int len = strlen (next_str);
/* Copy the strings into the allocated space. */
argcount = 0;
- VA_START (args, str0);
+ va_start (args, str0);
for (next_str = str0; next_str != NULL; next_str = va_arg (args, char *))
{
int len;
}
#endif /* not WINDOWS */
\f
-/* "Touch" FILE, i.e. make its atime and mtime equal to the time
- specified with TM. */
+/* "Touch" FILE, i.e. make its mtime ("modified time") equal the time
+ specified with TM. The atime ("access time") is set to the current
+ time. */
+
void
touch (const char *file, time_t tm)
{
#ifdef HAVE_STRUCT_UTIMBUF
struct utimbuf times;
- times.actime = times.modtime = tm;
#else
- time_t times[2];
- times[0] = times[1] = tm;
+ struct {
+ time_t actime;
+ time_t modtime;
+ } times;
#endif
-
+ times.modtime = tm;
+ times.actime = time (NULL);
if (utime (file, ×) == -1)
logprintf (LOG_NOTQUIET, "utime(%s): %s\n", file, strerror (errno));
}
if (!cut)
return xstrdup (file);
- result = (char *)xmalloc (cut - base + 1 + strlen (file) + 1);
+ result = xmalloc (cut - base + 1 + strlen (file) + 1);
memcpy (result, base, cut - base);
result[cut - base] = '/';
strcpy (result + (cut - base) + 1, file);
return result;
}
\f
-static int in_acclist PARAMS ((const char *const *, const char *, int));
+static int in_acclist (const char *const *, const char *, int);
/* Determine whether a file is acceptable to be followed, according to
lists of patterns to accept/reject. */
proclist (char **strlist, const char *s, enum accd flags)
{
char **x;
-
for (x = strlist; *x; x++)
- if (has_wildcards_p (*x))
- {
- if (fnmatch (*x, s, FNM_PATHNAME) == 0)
- break;
- }
- else
- {
- char *p = *x + ((flags & ALLABS) && (**x == '/')); /* Remove '/' */
- if (frontcmp (p, s))
- break;
- }
+ {
+ /* Remove leading '/' if ALLABS */
+ char *p = *x + ((flags & ALLABS) && (**x == '/'));
+ if (has_wildcards_p (p))
+ {
+ if (fnmatch (p, s, FNM_PATHNAME) == 0)
+ break;
+ }
+ else
+ {
+ if (frontcmp (p, s))
+ break;
+ }
+ }
return *x;
}
{
int length = 0;
int bufsize = 82;
- char *line = (char *)xmalloc (bufsize);
+ char *line = xmalloc (bufsize);
while (fgets (line + length, bufsize - length, fp))
{
/* Count v2. */
for (j = 0; v2[j]; j++);
/* Reallocate v1. */
- v1 = (char **)xrealloc (v1, (i + j + 1) * sizeof (char **));
+ v1 = xrealloc (v1, (i + j + 1) * sizeof (char **));
memcpy (v1 + i, v2, (j + 1) * sizeof (char *));
xfree (v2);
return v1;
}
+
+/* Append a freshly allocated copy of STR to VEC. If VEC is NULL, it
+ is allocated as needed. Return the new value of the vector. */
+
+char **
+vec_append (char **vec, const char *str)
+{
+ int cnt; /* count of vector elements, including
+ the one we're about to append */
+ if (vec != NULL)
+ {
+ for (cnt = 0; vec[cnt]; cnt++)
+ ;
+ ++cnt;
+ }
+ else
+ cnt = 1;
+ /* Reallocate the array to fit the new element and the NULL. */
+ vec = xrealloc (vec, (cnt + 1) * sizeof (char *));
+ /* Append a copy of STR to the vector. */
+ vec[cnt - 1] = xstrdup (str);
+ vec[cnt] = NULL;
+ return vec;
+}
\f
/* Sometimes it's useful to create "sets" of strings, i.e. special
hash tables where you want to store strings as keys and merely
usually improves readability."
This intentionally uses kilobyte (KB), megabyte (MB), etc. in their
- original computer science meaning of "multiples of 1024".
- Multiples of 1000 would be useless since Wget already adds thousand
- separators for legibility. We don't use the "*bibyte" names
- invented in 1998, and seldom used in practice. Wikipedia's entry
- on kilobyte discusses this in some detail. */
+ original computer science meaning of "powers of 1024". Powers of
+ 1000 would be useless since Wget already displays sizes with
+ thousand separators. We don't use the "*bibyte" names invented in
+ 1998, and seldom used in practice. Wikipedia's entry on kilobyte
+ discusses this in some detail. */
char *
human_readable (wgint n)
/* wgint is 32 bits wide: no number has more than 10 digits. */
else DIGITS_10 (1000000000);
#else
- /* wgint is 64 bits wide: handle numbers with more than 9 decimal
- digits. Constants are constructed by compile-time multiplication
- to avoid dealing with different notations for 64-bit constants
- (nnnL, nnnLL, and nnnI64, depending on the compiler). */
+ /* wgint is 64 bits wide: handle numbers with 9-19 decimal digits.
+ Constants are constructed by compile-time multiplication to avoid
+ dealing with different notations for 64-bit constants
+ (nL/nLL/nI64, depending on the compiler and architecture). */
else if (n < 10*(W)1000000000) DIGITS_10 (1000000000);
else if (n < 100*(W)1000000000) DIGITS_11 (10*(W)1000000000);
else if (n < 1000*(W)1000000000) DIGITS_12 (100*(W)1000000000);
static sigjmp_buf run_with_timeout_env;
-static RETSIGTYPE
+static void
abort_run_with_timeout (int sig)
{
assert (sig == SIGALRM);
static jmp_buf run_with_timeout_env;
-static RETSIGTYPE
+static void
abort_run_with_timeout (int sig)
{
assert (sig == SIGALRM);
#undef IS_ASCII
#undef IS_BASE64
#undef NEXT_BASE64_CHAR
+\f
+/* Simple merge sort for use by stable_sort. Implementation courtesy
+ Zeljko Vrba with additional debugging by Nenad Barbutov. */
+
+static void
+mergesort_internal (void *base, void *temp, size_t size, size_t from, size_t to,
+ int (*cmpfun) (const void *, const void *))
+{
+#define ELT(array, pos) ((char *)(array) + (pos) * size)
+ if (from < to)
+ {
+ size_t i, j, k;
+ size_t mid = (to + from) / 2;
+ mergesort_internal (base, temp, size, from, mid, cmpfun);
+ mergesort_internal (base, temp, size, mid + 1, to, cmpfun);
+ i = from;
+ j = mid + 1;
+ for (k = from; (i <= mid) && (j <= to); k++)
+ if (cmpfun (ELT (base, i), ELT (base, j)) <= 0)
+ memcpy (ELT (temp, k), ELT (base, i++), size);
+ else
+ memcpy (ELT (temp, k), ELT (base, j++), size);
+ while (i <= mid)
+ memcpy (ELT (temp, k++), ELT (base, i++), size);
+ while (j <= to)
+ memcpy (ELT (temp, k++), ELT (base, j++), size);
+ for (k = from; k <= to; k++)
+ memcpy (ELT (base, k), ELT (temp, k), size);
+ }
+#undef ELT
+}
+
+/* Stable sort with interface exactly like standard library's qsort.
+ Uses mergesort internally, allocating temporary storage with
+ alloca. */
+
+void
+stable_sort (void *base, size_t nmemb, size_t size,
+ int (*cmpfun) (const void *, const void *))
+{
+ if (size > 1)
+ {
+ void *temp = alloca (nmemb * size * sizeof (void *));
+ mergesort_internal (base, temp, size, 0, nmemb - 1, cmpfun);
+ }
+}