]> sjero.net Git - wget/blobdiff - src/utils.c
[svn] Extract timers to a separate file.
[wget] / src / utils.c
index 81c0d36b08dfbbed186168bfbd1f1600e2eee137..dc16d55afc5940d095b9ada5d33f4d6d77deb809 100644 (file)
@@ -1,5 +1,5 @@
 /* Various utility functions.
-   Copyright (C) 2003 Free Software Foundation, Inc.
+   Copyright (C) 2005 Free Software Foundation, Inc.
 
 This file is part of GNU Wget.
 
@@ -120,19 +120,6 @@ xstrdup_lower (const char *s)
   return copy;
 }
 
-/* Return a count of how many times CHR occurs in STRING. */
-
-int
-count_char (const char *string, char chr)
-{
-  const char *p;
-  int count = 0;
-  for (p = string; *p; p++)
-    if (*p == chr)
-      ++count;
-  return count;
-}
-
 /* Copy the string formed by two pointers (one on the beginning, other
    on the char after the last char) to a new, malloc-ed location.
    0-terminate it.  */
@@ -226,6 +213,54 @@ aprintf (const char *fmt, ...)
     }
   return NULL;                 /* unreached */
 }
+
+/* Concatenate the NULL-terminated list of string arguments into
+   freshly allocated space.  */
+
+char *
+concat_strings (const char *str0, ...)
+{
+  va_list args;
+  int saved_lengths[5];                /* inspired by Apache's apr_pstrcat */
+  char *ret, *p;
+
+  const char *next_str;
+  int total_length = 0;
+  int argcount;
+
+  /* Calculate the length of and allocate the resulting string. */
+
+  argcount = 0;
+  VA_START (args, str0);
+  for (next_str = str0; next_str != NULL; next_str = va_arg (args, char *))
+    {
+      int len = strlen (next_str);
+      if (argcount < countof (saved_lengths))
+       saved_lengths[argcount++] = len;
+      total_length += len;
+    }
+  va_end (args);
+  p = ret = xmalloc (total_length + 1);
+
+  /* Copy the strings into the allocated space. */
+
+  argcount = 0;
+  VA_START (args, str0);
+  for (next_str = str0; next_str != NULL; next_str = va_arg (args, char *))
+    {
+      int len;
+      if (argcount < countof (saved_lengths))
+       len = saved_lengths[argcount++];
+      else
+       len = strlen (next_str);
+      memcpy (p, next_str, len);
+      p += len;
+    }
+  va_end (args);
+  *p = '\0';
+
+  return ret;
+}
 \f
 /* Return pointer to a static char[] buffer in which zero-terminated
    string-representation of TM (in form hh:mm:ss) is printed.
@@ -523,6 +558,14 @@ fopen_excl (const char *fname, int binary)
     return NULL;
   return fdopen (fd, binary ? "wb" : "w");
 #else  /* not O_EXCL */
+  /* Manually check whether the file exists.  This is prone to race
+     conditions, but systems without O_EXCL haven't deserved
+     better.  */
+  if (file_exists_p (fname))
+    {
+      errno = EEXIST;
+      return NULL;
+    }
   return fopen (fname, binary ? "wb" : "w");
 #endif /* not O_EXCL */
 }
@@ -536,9 +579,7 @@ fopen_excl (const char *fname, int binary)
 int
 make_directory (const char *directory)
 {
-  int quit = 0;
-  int i;
-  int ret = 0;
+  int i, ret, quit = 0;
   char *dir;
 
   /* Make a copy of dir, to be able to write to it.  Otherwise, the
@@ -876,7 +917,7 @@ read_file (const char *file)
 {
   int fd;
   struct file_memory *fm;
-  wgint size;
+  long size;
   int inhibit_close = 0;
 
   /* Some magic in the finest tradition of Perl and its kin: if FILE
@@ -1039,91 +1080,6 @@ merge_vecs (char **v1, char **v2)
   xfree (v2);
   return v1;
 }
-
-/* A set of simple-minded routines to store strings in a linked list.
-   This used to also be used for searching, but now we have hash
-   tables for that.  */
-
-/* It's a shame that these simple things like linked lists and hash
-   tables (see hash.c) need to be implemented over and over again.  It
-   would be nice to be able to use the routines from glib -- see
-   www.gtk.org for details.  However, that would make Wget depend on
-   glib, and I want to avoid dependencies to external libraries for
-   reasons of convenience and portability (I suspect Wget is more
-   portable than anything ever written for Gnome).  */
-
-/* Append an element to the list.  If the list has a huge number of
-   elements, this can get slow because it has to find the list's
-   ending.  If you think you have to call slist_append in a loop,
-   think about calling slist_prepend() followed by slist_nreverse().  */
-
-slist *
-slist_append (slist *l, const char *s)
-{
-  slist *newel = xnew (slist);
-  slist *beg = l;
-
-  newel->string = xstrdup (s);
-  newel->next = NULL;
-
-  if (!l)
-    return newel;
-  /* Find the last element.  */
-  while (l->next)
-    l = l->next;
-  l->next = newel;
-  return beg;
-}
-
-/* Prepend S to the list.  Unlike slist_append(), this is O(1).  */
-
-slist *
-slist_prepend (slist *l, const char *s)
-{
-  slist *newel = xnew (slist);
-  newel->string = xstrdup (s);
-  newel->next = l;
-  return newel;
-}
-
-/* Destructively reverse L. */
-
-slist *
-slist_nreverse (slist *l)
-{
-  slist *prev = NULL;
-  while (l)
-    {
-      slist *next = l->next;
-      l->next = prev;
-      prev = l;
-      l = next;
-    }
-  return prev;
-}
-
-/* Is there a specific entry in the list?  */
-int
-slist_contains (slist *l, const char *s)
-{
-  for (; l; l = l->next)
-    if (!strcmp (l->string, s))
-      return 1;
-  return 0;
-}
-
-/* Free the whole slist.  */
-void
-slist_free (slist *l)
-{
-  while (l)
-    {
-      slist *n = l->next;
-      xfree (l->string);
-      xfree (l);
-      l = n;
-    }
-}
 \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
@@ -1154,6 +1110,22 @@ string_set_contains (struct hash_table *ht, const char *s)
   return hash_table_contains (ht, s);
 }
 
+static int
+string_set_to_array_mapper (void *key, void *value_ignored, void *arg)
+{
+  char ***arrayptr = (char ***) arg;
+  *(*arrayptr)++ = (char *) key;
+  return 0;
+}
+
+/* Convert the specified string set to array.  ARRAY should be large
+   enough to hold hash_table_count(ht) char pointers.  */
+
+void string_set_to_array (struct hash_table *ht, char **array)
+{
+  hash_table_map (ht, string_set_to_array_mapper, &array);
+}
+
 static int
 string_set_free_mapper (void *key, void *value_ignored, void *arg_ignored)
 {
@@ -1185,11 +1157,11 @@ free_keys_and_values (struct hash_table *ht)
 }
 
 \f
-/* Engine for legible and legible_large_int; add thousand separators
-   to numbers printed in strings.  */
+/* Add thousand separators to a number already in string form.  Used
+   by with_thousand_seps and with_thousand_seps_large.  */
 
 static char *
-legible_1 (const char *repr)
+add_thousand_seps (const char *repr)
 {
   static char outbuf[48];
   int i, i1, mod;
@@ -1225,145 +1197,176 @@ legible_1 (const char *repr)
   return outbuf;
 }
 
-/* Legible -- return a static pointer to the legibly printed wgint.  */
+/* Return a static pointer to the number printed with thousand
+   separators inserted at the right places.  */
 
 char *
-legible (wgint l)
+with_thousand_seps (wgint l)
 {
   char inbuf[24];
   /* Print the number into the buffer.  */
   number_to_string (inbuf, l);
-  return legible_1 (inbuf);
+  return add_thousand_seps (inbuf);
 }
 
 /* Write a string representation of LARGE_INT NUMBER into the provided
-   buffer.  The buffer should be able to accept 24 characters,
-   including the terminating zero.
+   buffer.
 
    It would be dangerous to use sprintf, because the code wouldn't
    work on a machine with gcc-provided long long support, but without
-   libc support for "%lld".  However, such platforms will typically
-   not have snprintf and will use our version, which does support
-   "%lld" where long longs are available.  */
+   libc support for "%lld".  However, such old systems platforms
+   typically lack snprintf and will end up using our version, which
+   does support "%lld" whereever long longs are available.  */
 
 static void
-large_int_to_string (char *buffer, LARGE_INT number)
+large_int_to_string (char *buffer, int bufsize, LARGE_INT number)
 {
-  snprintf (buffer, 24, LARGE_INT_FMT, number);
+  snprintf (buffer, bufsize, LARGE_INT_FMT, number);
 }
 
-/* The same as legible(), but works on LARGE_INT.  */
+/* The same as with_thousand_seps, but works on LARGE_INT.  */
 
 char *
-legible_large_int (LARGE_INT l)
+with_thousand_seps_large (LARGE_INT l)
 {
   char inbuf[48];
-  large_int_to_string (inbuf, l);
-  return legible_1 (inbuf);
+  large_int_to_string (inbuf, sizeof (inbuf), l);
+  return add_thousand_seps (inbuf);
+}
+
+/* N, a byte quantity, is converted to a human-readable abberviated
+   form a la sizes printed by `ls -lh'.  The result is written to a
+   static buffer, a pointer to which is returned.
+
+   Unlike `with_thousand_seps', this approximates to the nearest unit.
+   Quoting GNU libit: "Most people visually process strings of 3-4
+   digits effectively, but longer strings of digits are more prone to
+   misinterpretation.  Hence, converting to an abbreviated form
+   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.  */
+
+char *
+human_readable (wgint n)
+{
+  /* These suffixes are compatible with those of GNU `ls -lh'. */
+  static char powers[] =
+    {
+      'K',                     /* kilobyte, 2^10 bytes */
+      'M',                     /* megabyte, 2^20 bytes */
+      'G',                     /* gigabyte, 2^30 bytes */
+      'T',                     /* terabyte, 2^40 bytes */
+      'P',                     /* petabyte, 2^50 bytes */
+      'E',                     /* exabyte,  2^60 bytes */
+    };
+  static char buf[8];
+  int i;
+
+  /* If the quantity is smaller than 1K, just print it. */
+  if (n < 1024)
+    {
+      snprintf (buf, sizeof (buf), "%d", (int) n);
+      return buf;
+    }
+
+  /* Loop over powers, dividing N with 1024 in each iteration.  This
+     works unchanged for all sizes of wgint, while still avoiding
+     non-portable `long double' arithmetic.  */
+  for (i = 0; i < countof (powers); i++)
+    {
+      /* At each iteration N is greater than the *subsequent* power.
+        That way N/1024.0 produces a decimal number in the units of
+        *this* power.  */
+      if ((n >> 10) < 1024 || i == countof (powers) - 1)
+       {
+         /* Must cast to long first because MS VC can't directly cast
+            __int64 to double.  (This is safe because N is known to
+            be <2**20.)  */
+         double val = (double) (long) n / 1024.0;
+         /* Print values smaller than 10 with one decimal digits, and
+            others without any decimals.  */
+         snprintf (buf, sizeof (buf), "%.*f%c",
+                   val < 10 ? 1 : 0, val, powers[i]);
+         return buf;
+       }
+      n >>= 10;
+    }
+  return NULL;                 /* unreached */
 }
 
-/* Count the digits in an integer number.  */
+/* Count the digits in the provided number.  Used to allocate space
+   when printing numbers.  */
+
 int
 numdigit (wgint number)
 {
   int cnt = 1;
   if (number < 0)
-    {
-      number = -number;
-      ++cnt;
-    }
-  while ((number /= 10) > 0)
+    ++cnt;                     /* accomodate '-' */
+  while ((number /= 10) != 0)
     ++cnt;
   return cnt;
 }
 
-#define ONE_DIGIT(figure) *p++ = n / (figure) + '0'
-#define ONE_DIGIT_ADVANCE(figure) (ONE_DIGIT (figure), n %= (figure))
-
-#define DIGITS_1(figure) ONE_DIGIT (figure)
-#define DIGITS_2(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_1 ((figure) / 10)
-#define DIGITS_3(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_2 ((figure) / 10)
-#define DIGITS_4(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_3 ((figure) / 10)
-#define DIGITS_5(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_4 ((figure) / 10)
-#define DIGITS_6(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_5 ((figure) / 10)
-#define DIGITS_7(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_6 ((figure) / 10)
-#define DIGITS_8(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_7 ((figure) / 10)
-#define DIGITS_9(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_8 ((figure) / 10)
-#define DIGITS_10(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_9 ((figure) / 10)
-
-/* DIGITS_<11-20> are only used on machines with 64-bit numbers. */
-
-#define DIGITS_11(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_10 ((figure) / 10)
-#define DIGITS_12(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_11 ((figure) / 10)
-#define DIGITS_13(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_12 ((figure) / 10)
-#define DIGITS_14(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_13 ((figure) / 10)
-#define DIGITS_15(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_14 ((figure) / 10)
-#define DIGITS_16(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_15 ((figure) / 10)
-#define DIGITS_17(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_16 ((figure) / 10)
-#define DIGITS_18(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_17 ((figure) / 10)
-#define DIGITS_19(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_18 ((figure) / 10)
-
-/* It is annoying that we have three different syntaxes for 64-bit constants:
-    - nnnL for 64-bit systems, where they are of type long;
-    - nnnLL for 32-bit systems that support long long;
-    - nnnI64 for MS compiler on Windows, which doesn't support long long. */
-
-#if SIZEOF_LONG > 4
-/* If long is large enough, use long constants. */
-# define C10000000000 10000000000L
-# define C100000000000 100000000000L
-# define C1000000000000 1000000000000L
-# define C10000000000000 10000000000000L
-# define C100000000000000 100000000000000L
-# define C1000000000000000 1000000000000000L
-# define C10000000000000000 10000000000000000L
-# define C100000000000000000 100000000000000000L
-# define C1000000000000000000 1000000000000000000L
-#else
-# if SIZEOF_LONG_LONG != 0
-/* Otherwise, if long long is available, use long long constants. */
-#  define C10000000000 10000000000LL
-#  define C100000000000 100000000000LL
-#  define C1000000000000 1000000000000LL
-#  define C10000000000000 10000000000000LL
-#  define C100000000000000 100000000000000LL
-#  define C1000000000000000 1000000000000000LL
-#  define C10000000000000000 10000000000000000LL
-#  define C100000000000000000 100000000000000000LL
-#  define C1000000000000000000 1000000000000000000LL
-# else
-#  if defined(WINDOWS)
-/* Use __int64 constants under Windows. */
-#   define C10000000000 10000000000I64
-#   define C100000000000 100000000000I64
-#   define C1000000000000 1000000000000I64
-#   define C10000000000000 10000000000000I64
-#   define C100000000000000 100000000000000I64
-#   define C1000000000000000 1000000000000000I64
-#   define C10000000000000000 10000000000000000I64
-#   define C100000000000000000 100000000000000000I64
-#   define C1000000000000000000 1000000000000000000I64
-#  endif
-# endif
-#endif
+#define PR(mask) *p++ = n / (mask) + '0'
+
+/* DIGITS_<D> is used to print a D-digit number and should be called
+   with mask==10^(D-1).  It prints n/mask (the first digit), reducing
+   n to n%mask (the remaining digits), and calling DIGITS_<D-1>.
+   Recursively this continues until DIGITS_1 is invoked.  */
+
+#define DIGITS_1(mask) PR (mask)
+#define DIGITS_2(mask) PR (mask), n %= (mask), DIGITS_1 ((mask) / 10)
+#define DIGITS_3(mask) PR (mask), n %= (mask), DIGITS_2 ((mask) / 10)
+#define DIGITS_4(mask) PR (mask), n %= (mask), DIGITS_3 ((mask) / 10)
+#define DIGITS_5(mask) PR (mask), n %= (mask), DIGITS_4 ((mask) / 10)
+#define DIGITS_6(mask) PR (mask), n %= (mask), DIGITS_5 ((mask) / 10)
+#define DIGITS_7(mask) PR (mask), n %= (mask), DIGITS_6 ((mask) / 10)
+#define DIGITS_8(mask) PR (mask), n %= (mask), DIGITS_7 ((mask) / 10)
+#define DIGITS_9(mask) PR (mask), n %= (mask), DIGITS_8 ((mask) / 10)
+#define DIGITS_10(mask) PR (mask), n %= (mask), DIGITS_9 ((mask) / 10)
+
+/* DIGITS_<11-20> are only used on machines with 64-bit wgints. */
+
+#define DIGITS_11(mask) PR (mask), n %= (mask), DIGITS_10 ((mask) / 10)
+#define DIGITS_12(mask) PR (mask), n %= (mask), DIGITS_11 ((mask) / 10)
+#define DIGITS_13(mask) PR (mask), n %= (mask), DIGITS_12 ((mask) / 10)
+#define DIGITS_14(mask) PR (mask), n %= (mask), DIGITS_13 ((mask) / 10)
+#define DIGITS_15(mask) PR (mask), n %= (mask), DIGITS_14 ((mask) / 10)
+#define DIGITS_16(mask) PR (mask), n %= (mask), DIGITS_15 ((mask) / 10)
+#define DIGITS_17(mask) PR (mask), n %= (mask), DIGITS_16 ((mask) / 10)
+#define DIGITS_18(mask) PR (mask), n %= (mask), DIGITS_17 ((mask) / 10)
+#define DIGITS_19(mask) PR (mask), n %= (mask), DIGITS_18 ((mask) / 10)
 
 /* SPRINTF_WGINT is used by number_to_string to handle pathological
-   cases and to portably support strange sizes of wgint. */
+   cases and to portably support strange sizes of wgint.  Ideally this
+   would just use "%j" and intmax_t, but many systems don't support
+   it, so it's used only if nothing else works.  */
 #if SIZEOF_LONG >= SIZEOF_WGINT
-#  define SPRINTF_WGINT(buf, n) sprintf(buf, "%ld", (long) (n))
+#  define SPRINTF_WGINT(buf, n) sprintf (buf, "%ld", (long) (n))
 #else
 # if SIZEOF_LONG_LONG >= SIZEOF_WGINT
-#   define SPRINTF_WGINT(buf, n) sprintf(buf, "%lld", (long long) (n))
+#   define SPRINTF_WGINT(buf, n) sprintf (buf, "%lld", (long long) (n))
 # else
 #  ifdef WINDOWS
-#   define SPRINTF_WGINT(buf, n) sprintf(buf, "%I64", (__int64) (n))
+#   define SPRINTF_WGINT(buf, n) sprintf (buf, "%I64", (__int64) (n))
+#  else
+#   define SPRINTF_WGINT(buf, n) sprintf (buf, "%j", (intmax_t) (n))
 #  endif
 # endif
 #endif
 
+/* Shorthand for casting to wgint. */
+#define W wgint
+
 /* Print NUMBER to BUFFER in base 10.  This is equivalent to
-   `sprintf(buffer, "%lld", (long long) number)', only much faster and
-   portable to machines without long long.
+   `sprintf(buffer, "%lld", (long long) number)', only typically much
+   faster and portable to machines without long long.
 
    The speedup may make a difference in programs that frequently
    convert numbers to strings.  Some implementations of sprintf,
@@ -1397,8 +1400,7 @@ number_to_string (char *buffer, wgint number)
     {
       if (n < -WGINT_MAX)
        {
-         /* We cannot print a '-' and assign -n to n because -n would
-            overflow.  Let sprintf deal with this border case.  */
+         /* -n would overflow.  Have sprintf deal with this.  */
          SPRINTF_WGINT (buffer, n);
          p += strlen (buffer);
          return p;
@@ -1408,31 +1410,37 @@ number_to_string (char *buffer, wgint number)
       n = -n;
     }
 
-  if      (n < 10)                   { DIGITS_1 (1); }
-  else if (n < 100)                  { DIGITS_2 (10); }
-  else if (n < 1000)                 { DIGITS_3 (100); }
-  else if (n < 10000)                { DIGITS_4 (1000); }
-  else if (n < 100000)               { DIGITS_5 (10000); }
-  else if (n < 1000000)              { DIGITS_6 (100000); }
-  else if (n < 10000000)             { DIGITS_7 (1000000); }
-  else if (n < 100000000)            { DIGITS_8 (10000000); }
-  else if (n < 1000000000)           { DIGITS_9 (100000000); }
+  /* Use the DIGITS_ macro appropriate for N's number of digits.  That
+     way printing any N is fully open-coded without a loop or jump.
+     (Also see description of DIGITS_*.)  */
+
+  if      (n < 10)                       DIGITS_1 (1);
+  else if (n < 100)                      DIGITS_2 (10);
+  else if (n < 1000)                     DIGITS_3 (100);
+  else if (n < 10000)                    DIGITS_4 (1000);
+  else if (n < 100000)                   DIGITS_5 (10000);
+  else if (n < 1000000)                  DIGITS_6 (100000);
+  else if (n < 10000000)                 DIGITS_7 (1000000);
+  else if (n < 100000000)                DIGITS_8 (10000000);
+  else if (n < 1000000000)               DIGITS_9 (100000000);
 #if SIZEOF_WGINT == 4
-  /* wgint is four bytes long: we're done. */
-  /* ``if (1)'' serves only to preserve editor indentation. */
-  else if (1)                        { DIGITS_10 (1000000000); }
+  /* wgint is 32 bits wide: no number has more than 10 digits. */
+  else                                   DIGITS_10 (1000000000);
 #else
-  /* wgint is 64 bits long -- make sure to process all the digits. */
-  else if (n < C10000000000)         { DIGITS_10 (1000000000); }
-  else if (n < C100000000000)        { DIGITS_11 (C10000000000); }
-  else if (n < C1000000000000)       { DIGITS_12 (C100000000000); }
-  else if (n < C10000000000000)      { DIGITS_13 (C1000000000000); }
-  else if (n < C100000000000000)     { DIGITS_14 (C10000000000000); }
-  else if (n < C1000000000000000)    { DIGITS_15 (C100000000000000); }
-  else if (n < C10000000000000000)   { DIGITS_16 (C1000000000000000); }
-  else if (n < C100000000000000000)  { DIGITS_17 (C10000000000000000); }
-  else if (n < C1000000000000000000) { DIGITS_18 (C100000000000000000); }
-  else                               { DIGITS_19 (C1000000000000000000); }
+  /* 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).  */
+  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);
+  else if (n < 10000*(W)1000000000)      DIGITS_13 (1000*(W)1000000000);
+  else if (n < 100000*(W)1000000000)     DIGITS_14 (10000*(W)1000000000);
+  else if (n < 1000000*(W)1000000000)    DIGITS_15 (100000*(W)1000000000);
+  else if (n < 10000000*(W)1000000000)   DIGITS_16 (1000000*(W)1000000000);
+  else if (n < 100000000*(W)1000000000)  DIGITS_17 (10000000*(W)1000000000);
+  else if (n < 1000000000*(W)1000000000) DIGITS_18 (100000000*(W)1000000000);
+  else                                   DIGITS_19 (1000000000*(W)1000000000);
 #endif
 
   *p = '\0';
@@ -1441,9 +1449,8 @@ number_to_string (char *buffer, wgint number)
   return p;
 }
 
-#undef ONE_DIGIT
-#undef ONE_DIGIT_ADVANCE
-
+#undef PR
+#undef W
 #undef DIGITS_1
 #undef DIGITS_2
 #undef DIGITS_3
@@ -1508,322 +1515,6 @@ number_to_static_string (wgint number)
   return buf;
 }
 \f
-/* Support for timers. */
-
-#undef TIMER_WINDOWS
-#undef TIMER_GETTIMEOFDAY
-#undef TIMER_TIME
-
-/* Depending on the OS and availability of gettimeofday(), one and
-   only one of the above constants will be defined.  Virtually all
-   modern Unix systems will define TIMER_GETTIMEOFDAY; Windows will
-   use TIMER_WINDOWS.  TIMER_TIME is a catch-all method for
-   non-Windows systems without gettimeofday.
-
-   #### Perhaps we should also support ftime(), which exists on old
-   BSD 4.2-influenced systems?  (It also existed under MS DOS Borland
-   C, if memory serves me.)  */
-
-#ifdef WINDOWS
-# define TIMER_WINDOWS
-#else  /* not WINDOWS */
-# ifdef HAVE_GETTIMEOFDAY
-#  define TIMER_GETTIMEOFDAY
-# else
-#  define TIMER_TIME
-# endif
-#endif /* not WINDOWS */
-
-#ifdef TIMER_GETTIMEOFDAY
-typedef struct timeval wget_sys_time;
-#endif
-
-#ifdef TIMER_TIME
-typedef time_t wget_sys_time;
-#endif
-
-#ifdef TIMER_WINDOWS
-typedef ULARGE_INTEGER wget_sys_time;
-#endif
-
-struct wget_timer {
-  /* Whether the start time has been initialized. */
-  int initialized;
-
-  /* The starting point in time which, subtracted from the current
-     time, yields elapsed time. */
-  wget_sys_time start;
-
-  /* The most recent elapsed time, calculated by wtimer_elapsed().
-     Measured in milliseconds.  */
-  double elapsed_last;
-
-  /* Approximately, the time elapsed between the true start of the
-     measurement and the time represented by START.  */
-  double elapsed_pre_start;
-};
-
-/* Allocate a timer.  Calling wtimer_read on the timer will return
-   zero.  It is not legal to call wtimer_update with a freshly
-   allocated timer -- use wtimer_reset first.  */
-
-struct wget_timer *
-wtimer_allocate (void)
-{
-  struct wget_timer *wt = xnew (struct wget_timer);
-  xzero (*wt);
-  return wt;
-}
-
-/* Allocate a new timer and reset it.  Return the new timer. */
-
-struct wget_timer *
-wtimer_new (void)
-{
-  struct wget_timer *wt = wtimer_allocate ();
-  wtimer_reset (wt);
-  return wt;
-}
-
-/* Free the resources associated with the timer.  Its further use is
-   prohibited.  */
-
-void
-wtimer_delete (struct wget_timer *wt)
-{
-  xfree (wt);
-}
-
-/* Store system time to WST.  */
-
-static void
-wtimer_sys_set (wget_sys_time *wst)
-{
-#ifdef TIMER_GETTIMEOFDAY
-  gettimeofday (wst, NULL);
-#endif
-
-#ifdef TIMER_TIME
-  time (wst);
-#endif
-
-#ifdef TIMER_WINDOWS
-  /* We use GetSystemTime to get the elapsed time.  MSDN warns that
-     system clock adjustments can skew the output of GetSystemTime
-     when used as a timer and gives preference to GetTickCount and
-     high-resolution timers.  But GetTickCount can overflow, and hires
-     timers are typically used for profiling, not for regular time
-     measurement.  Since we handle clock skew anyway, we just use
-     GetSystemTime.  */
-  FILETIME ft;
-  SYSTEMTIME st;
-  GetSystemTime (&st);
-
-  /* As recommended by MSDN, we convert SYSTEMTIME to FILETIME, copy
-     FILETIME to ULARGE_INTEGER, and use regular 64-bit integer
-     arithmetic on that.  */
-  SystemTimeToFileTime (&st, &ft);
-  wst->HighPart = ft.dwHighDateTime;
-  wst->LowPart  = ft.dwLowDateTime;
-#endif
-}
-
-/* Reset timer WT.  This establishes the starting point from which
-   wtimer_elapsed() will return the number of elapsed milliseconds.
-   It is allowed to reset a previously used timer.
-
-   If a non-zero value is used as START, the timer's values will be
-   offset by START.  */
-
-void
-wtimer_reset (struct wget_timer *wt)
-{
-  /* Set the start time to the current time. */
-  wtimer_sys_set (&wt->start);
-  wt->elapsed_last = 0;
-  wt->elapsed_pre_start = 0;
-  wt->initialized = 1;
-}
-
-static double
-wtimer_sys_diff (wget_sys_time *wst1, wget_sys_time *wst2)
-{
-#ifdef TIMER_GETTIMEOFDAY
-  return ((double)(wst1->tv_sec - wst2->tv_sec) * 1000
-         + (double)(wst1->tv_usec - wst2->tv_usec) / 1000);
-#endif
-
-#ifdef TIMER_TIME
-  return 1000 * (*wst1 - *wst2);
-#endif
-
-#ifdef WINDOWS
-  /* VC++ 6 doesn't support direct cast of uint64 to double.  To work
-     around this, we subtract, then convert to signed, then finally to
-     double.  */
-  return (double)(signed __int64)(wst1->QuadPart - wst2->QuadPart) / 10000;
-#endif
-}
-
-/* Update the timer's elapsed interval.  This function causes the
-   timer to call gettimeofday (or time(), etc.) to update its idea of
-   current time.  To get the elapsed interval in milliseconds, use
-   wtimer_read.
-
-   This function handles clock skew, i.e. time that moves backwards is
-   ignored.  */
-
-void
-wtimer_update (struct wget_timer *wt)
-{
-  wget_sys_time now;
-  double elapsed;
-
-  assert (wt->initialized != 0);
-
-  wtimer_sys_set (&now);
-  elapsed = wt->elapsed_pre_start + wtimer_sys_diff (&now, &wt->start);
-
-  /* Ideally we'd just return the difference between NOW and
-     wt->start.  However, the system timer can be set back, and we
-     could return a value smaller than when we were last called, even
-     a negative value.  Both of these would confuse the callers, which
-     expect us to return monotonically nondecreasing values.
-
-     Therefore: if ELAPSED is smaller than its previous known value,
-     we reset wt->start to the current time and effectively start
-     measuring from this point.  But since we don't want the elapsed
-     value to start from zero, we set elapsed_pre_start to the last
-     elapsed time and increment all future calculations by that
-     amount.  */
-
-  if (elapsed < wt->elapsed_last)
-    {
-      wt->start = now;
-      wt->elapsed_pre_start = wt->elapsed_last;
-      elapsed = wt->elapsed_last;
-    }
-
-  wt->elapsed_last = elapsed;
-}
-
-/* Return the elapsed time in milliseconds between the last call to
-   wtimer_reset and the last call to wtimer_update.
-
-   A typical use of the timer interface would be:
-
-       struct wtimer *timer = wtimer_new ();
-       ... do something that takes a while ...
-       wtimer_update ();
-       double msecs = wtimer_read ();  */
-
-double
-wtimer_read (const struct wget_timer *wt)
-{
-  return wt->elapsed_last;
-}
-
-/* Return the assessed granularity of the timer implementation, in
-   milliseconds.  This is used by code that tries to substitute a
-   better value for timers that have returned zero.  */
-
-double
-wtimer_granularity (void)
-{
-#ifdef TIMER_GETTIMEOFDAY
-  /* Granularity of gettimeofday varies wildly between architectures.
-     However, it appears that on modern machines it tends to be better
-     than 1ms.  Assume 100 usecs.  (Perhaps the configure process
-     could actually measure this?)  */
-  return 0.1;
-#endif
-
-#ifdef TIMER_TIME
-  return 1000;
-#endif
-
-#ifdef TIMER_WINDOWS
-  /* According to MSDN, GetSystemTime returns a broken-down time
-     structure the smallest member of which are milliseconds.  */
-  return 1;
-#endif
-}
-\f
-/* This should probably be at a better place, but it doesn't really
-   fit into html-parse.c.  */
-
-/* The function returns the pointer to the malloc-ed quoted version of
-   string s.  It will recognize and quote numeric and special graphic
-   entities, as per RFC1866:
-
-   `&' -> `&amp;'
-   `<' -> `&lt;'
-   `>' -> `&gt;'
-   `"' -> `&quot;'
-   SP  -> `&#32;'
-
-   No other entities are recognized or replaced.  */
-char *
-html_quote_string (const char *s)
-{
-  const char *b = s;
-  char *p, *res;
-  int i;
-
-  /* Pass through the string, and count the new size.  */
-  for (i = 0; *s; s++, i++)
-    {
-      if (*s == '&')
-       i += 4;                 /* `amp;' */
-      else if (*s == '<' || *s == '>')
-       i += 3;                 /* `lt;' and `gt;' */
-      else if (*s == '\"')
-       i += 5;                 /* `quot;' */
-      else if (*s == ' ')
-       i += 4;                 /* #32; */
-    }
-  res = (char *)xmalloc (i + 1);
-  s = b;
-  for (p = res; *s; s++)
-    {
-      switch (*s)
-       {
-       case '&':
-         *p++ = '&';
-         *p++ = 'a';
-         *p++ = 'm';
-         *p++ = 'p';
-         *p++ = ';';
-         break;
-       case '<': case '>':
-         *p++ = '&';
-         *p++ = (*s == '<' ? 'l' : 'g');
-         *p++ = 't';
-         *p++ = ';';
-         break;
-       case '\"':
-         *p++ = '&';
-         *p++ = 'q';
-         *p++ = 'u';
-         *p++ = 'o';
-         *p++ = 't';
-         *p++ = ';';
-         break;
-       case ' ':
-         *p++ = '&';
-         *p++ = '#';
-         *p++ = '3';
-         *p++ = '2';
-         *p++ = ';';
-         break;
-       default:
-         *p++ = *s;
-       }
-    }
-  *p = '\0';
-  return res;
-}
-
 /* Determine the width of the terminal we're running on.  If that's
    not possible, return 0.  */
 
@@ -1918,40 +1609,6 @@ random_float (void)
   int rnd3 = random_number (1000);
   return rnd1 / 1000.0 + rnd2 / 1000000.0 + rnd3 / 1000000000.0;
 }
-
-#if 0
-/* A debugging function for checking whether an MD5 library works. */
-
-#include "gen-md5.h"
-
-char *
-debug_test_md5 (char *buf)
-{
-  unsigned char raw[16];
-  static char res[33];
-  unsigned char *p1;
-  char *p2;
-  int cnt;
-  ALLOCA_MD5_CONTEXT (ctx);
-
-  gen_md5_init (ctx);
-  gen_md5_update ((unsigned char *)buf, strlen (buf), ctx);
-  gen_md5_finish (ctx, raw);
-
-  p1 = raw;
-  p2 = res;
-  cnt = 16;
-  while (cnt--)
-    {
-      *p2++ = XNUM_TO_digit (*p1 >> 4);
-      *p2++ = XNUM_TO_digit (*p1 & 0xf);
-      ++p1;
-    }
-  *p2 = '\0';
-
-  return res;
-}
-#endif
 \f
 /* Implementation of run_with_timeout, a generic timeout-forcing
    routine for systems with Unix-like signal handling.  */
@@ -2005,7 +1662,7 @@ alarm_set (double timeout)
   struct itimerval itv;
   xzero (itv);
   itv.it_value.tv_sec = (long) timeout;
-  itv.it_value.tv_usec = 1000000L * (timeout - (long)timeout);
+  itv.it_value.tv_usec = 1000000 * (timeout - (long)timeout);
   if (itv.it_value.tv_sec == 0 && itv.it_value.tv_usec == 0)
     /* Ensure that we wait for at least the minimum interval.
        Specifying zero would mean "wait forever".  */
@@ -2057,8 +1714,8 @@ alarm_cancel (void)
      * It works with both SYSV and BSD signals because it doesn't
        depend on the default setting of SA_RESTART.
 
-     * It doesn't special handler setup beyond a simple call to
-       signal().  (It does use sigsetjmp/siglongjmp, but they're
+     * It doesn't require special handler setup beyond a simple call
+       to signal().  (It does use sigsetjmp/siglongjmp, but they're
        optional.)
 
    The only downside is that, if FUN allocates internal resources that
@@ -2122,11 +1779,12 @@ xsleep (double seconds)
 #ifdef HAVE_NANOSLEEP
   /* nanosleep is the preferred interface because it offers high
      accuracy and, more importantly, because it allows us to reliably
-     restart after having been interrupted by a signal such as
-     SIGWINCH.  */
+     restart receiving a signal such as SIGWINCH.  (There was an
+     actual Debian bug report about --limit-rate malfunctioning while
+     the terminal was being resized.)  */
   struct timespec sleep, remaining;
   sleep.tv_sec = (long) seconds;
-  sleep.tv_nsec = 1000000000L * (seconds - (long) seconds);
+  sleep.tv_nsec = 1000000000 * (seconds - (long) seconds);
   while (nanosleep (&sleep, &remaining) < 0 && errno == EINTR)
     /* If nanosleep has been interrupted by a signal, adjust the
        sleeping period and return to sleep.  */
@@ -2142,12 +1800,17 @@ xsleep (double seconds)
       sleep (seconds);
       seconds -= (long) seconds;
     }
-  usleep (seconds * 1000000L);
+  usleep (seconds * 1000000);
 #else  /* not HAVE_USLEEP */
 #ifdef HAVE_SELECT
+  /* Note that, although Windows supports select, this sleeping
+     strategy doesn't work there because Winsock's select doesn't
+     implement timeout when it is passed NULL pointers for all fd
+     sets.  (But it does work under Cygwin, which implements its own
+     select.)  */
   struct timeval sleep;
   sleep.tv_sec = (long) seconds;
-  sleep.tv_usec = 1000000L * (seconds - (long) seconds);
+  sleep.tv_usec = 1000000 * (seconds - (long) seconds);
   select (0, NULL, NULL, NULL, &sleep);
   /* If select returns -1 and errno is EINTR, it means we were
      interrupted by a signal.  But without knowing how long we've
@@ -2161,3 +1824,143 @@ xsleep (double seconds)
 }
 
 #endif /* not WINDOWS */
+
+/* Encode the string S of length LENGTH to base64 format and place it
+   to STORE.  STORE will be 0-terminated, and must point to a writable
+   buffer of at least 1+BASE64_LENGTH(length) bytes.  */
+
+void
+base64_encode (const char *s, char *store, int length)
+{
+  /* Conversion table.  */
+  static char tbl[64] = {
+    'A','B','C','D','E','F','G','H',
+    'I','J','K','L','M','N','O','P',
+    'Q','R','S','T','U','V','W','X',
+    'Y','Z','a','b','c','d','e','f',
+    'g','h','i','j','k','l','m','n',
+    'o','p','q','r','s','t','u','v',
+    'w','x','y','z','0','1','2','3',
+    '4','5','6','7','8','9','+','/'
+  };
+  int i;
+  unsigned char *p = (unsigned char *)store;
+
+  /* Transform the 3x8 bits to 4x6 bits, as required by base64.  */
+  for (i = 0; i < length; i += 3)
+    {
+      *p++ = tbl[s[0] >> 2];
+      *p++ = tbl[((s[0] & 3) << 4) + (s[1] >> 4)];
+      *p++ = tbl[((s[1] & 0xf) << 2) + (s[2] >> 6)];
+      *p++ = tbl[s[2] & 0x3f];
+      s += 3;
+    }
+  /* Pad the result if necessary...  */
+  if (i == length + 1)
+    *(p - 1) = '=';
+  else if (i == length + 2)
+    *(p - 1) = *(p - 2) = '=';
+  /* ...and zero-terminate it.  */
+  *p = '\0';
+}
+
+#define IS_ASCII(c) (((c) & 0x80) == 0)
+#define IS_BASE64(c) ((IS_ASCII (c) && base64_char_to_value[c] >= 0) || c == '=')
+
+/* Get next character from the string, except that non-base64
+   characters are ignored, as mandated by rfc2045.  */
+#define NEXT_BASE64_CHAR(c, p) do {                    \
+  c = *p++;                                            \
+} while (c != '\0' && !IS_BASE64 (c))
+
+/* Decode data from BASE64 (assumed to be encoded as base64) into
+   memory pointed to by TO.  TO should be large enough to accomodate
+   the decoded data, which is guaranteed to be less than
+   strlen(base64).
+
+   Since TO is assumed to contain binary data, it is not
+   NUL-terminated.  The function returns the length of the data
+   written to TO.  -1 is returned in case of error caused by malformed
+   base64 input.  */
+
+int
+base64_decode (const char *base64, char *to)
+{
+  /* Table of base64 values for first 128 characters.  */
+  static short base64_char_to_value[128] =
+    {
+      -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, /*   0-  9 */
+      -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, /*  10- 19 */
+      -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, /*  20- 29 */
+      -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, /*  30- 39 */
+      -1,  -1,  -1,  62,  -1,  -1,  -1,  63,  52,  53, /*  40- 49 */
+      54,  55,  56,  57,  58,  59,  60,  61,  -1,  -1, /*  50- 59 */
+      -1,  -1,  -1,  -1,  -1,  0,   1,   2,   3,   4,  /*  60- 69 */
+      5,   6,   7,   8,   9,   10,  11,  12,  13,  14, /*  70- 79 */
+      15,  16,  17,  18,  19,  20,  21,  22,  23,  24, /*  80- 89 */
+      25,  -1,  -1,  -1,  -1,  -1,  -1,  26,  27,  28, /*  90- 99 */
+      29,  30,  31,  32,  33,  34,  35,  36,  37,  38, /* 100-109 */
+      39,  40,  41,  42,  43,  44,  45,  46,  47,  48, /* 110-119 */
+      49,  50,  51,  -1,  -1,  -1,  -1,  -1            /* 120-127 */
+    };
+
+  const char *p = base64;
+  char *q = to;
+
+  while (1)
+    {
+      unsigned char c;
+      unsigned long value;
+
+      /* Process first byte of a quadruplet.  */
+      NEXT_BASE64_CHAR (c, p);
+      if (!c)
+       break;
+      if (c == '=')
+       return -1;              /* illegal '=' while decoding base64 */
+      value = base64_char_to_value[c] << 18;
+
+      /* Process scond byte of a quadruplet.  */
+      NEXT_BASE64_CHAR (c, p);
+      if (!c)
+       return -1;              /* premature EOF while decoding base64 */
+      if (c == '=')
+       return -1;              /* illegal `=' while decoding base64 */
+      value |= base64_char_to_value[c] << 12;
+      *q++ = value >> 16;
+
+      /* Process third byte of a quadruplet.  */
+      NEXT_BASE64_CHAR (c, p);
+      if (!c)
+       return -1;              /* premature EOF while decoding base64 */
+
+      if (c == '=')
+       {
+         NEXT_BASE64_CHAR (c, p);
+         if (!c)
+           return -1;          /* premature EOF while decoding base64 */
+         if (c != '=')
+           return -1;          /* padding `=' expected but not found */
+         continue;
+       }
+
+      value |= base64_char_to_value[c] << 6;
+      *q++ = 0xff & value >> 8;
+
+      /* Process fourth byte of a quadruplet.  */
+      NEXT_BASE64_CHAR (c, p);
+      if (!c)
+       return -1;              /* premature EOF while decoding base64 */
+      if (c == '=')
+       continue;
+
+      value |= base64_char_to_value[c];
+      *q++ = 0xff & value;
+    }
+
+  return q - to;
+}
+
+#undef IS_ASCII
+#undef IS_BASE64
+#undef NEXT_BASE64_CHAR