]> sjero.net Git - wget/blobdiff - src/utils.c
[svn] Allow --header to contain ",".
[wget] / src / utils.c
index dc16d55afc5940d095b9ada5d33f4d6d77deb809..549f7a47ed44c2e1effd2fd9741066055a093ef7 100644 (file)
@@ -211,7 +211,6 @@ aprintf (const char *fmt, ...)
        size <<= 1;             /* twice the old size */
       str = xrealloc (str, size);
     }
-  return NULL;                 /* unreached */
 }
 
 /* Concatenate the NULL-terminated list of string arguments into
@@ -358,19 +357,23 @@ fork_to_background (void)
 }
 #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, &times) == -1)
     logprintf (LOG_NOTQUIET, "utime(%s): %s\n", file, strerror (errno));
 }
@@ -678,19 +681,21 @@ static char *
 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;
 }
 
@@ -1080,6 +1085,30 @@ merge_vecs (char **v1, char **v2)
   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
@@ -1245,11 +1274,11 @@ with_thousand_seps_large (LARGE_INT l)
    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)
@@ -1825,12 +1854,17 @@ 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.  */
+/* Encode the string STR of length LENGTH to base64 format and place it
+   to B64STORE.  The output will be \0-terminated, and must point to a
+   writable buffer of at least 1+BASE64_LENGTH(length) bytes.  It
+   returns the length of the resulting base64 data, not counting the
+   terminating zero.
 
-void
-base64_encode (const char *s, char *store, int length)
+   This implementation will not emit newlines after 76 characters of
+   base64 data.  */
+
+int
+base64_encode (const char *str, int length, char *b64store)
 {
   /* Conversion table.  */
   static char tbl[64] = {
@@ -1844,7 +1878,8 @@ base64_encode (const char *s, char *store, int length)
     '4','5','6','7','8','9','+','/'
   };
   int i;
-  unsigned char *p = (unsigned char *)store;
+  const unsigned char *s = (const unsigned char *) str;
+  char *p = b64store;
 
   /* Transform the 3x8 bits to 4x6 bits, as required by base64.  */
   for (i = 0; i < length; i += 3)
@@ -1855,13 +1890,17 @@ base64_encode (const char *s, char *store, int length)
       *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';
+
+  return p - b64store;
 }
 
 #define IS_ASCII(c) (((c) & 0x80) == 0)
@@ -1886,7 +1925,8 @@ base64_encode (const char *s, char *store, int length)
 int
 base64_decode (const char *base64, char *to)
 {
-  /* Table of base64 values for first 128 characters.  */
+  /* Table of base64 values for first 128 characters.  Note that this
+     assumes ASCII (but so does Wget in other places).  */
   static short base64_char_to_value[128] =
     {
       -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, /*   0-  9 */
@@ -1964,3 +2004,49 @@ base64_decode (const char *base64, char *to)
 #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) PARAMS ((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) PARAMS ((const void *, const void *)))
+{
+  if (size > 1)
+    {
+      void *temp = alloca (nmemb * size * sizeof (void *));
+      mergesort_internal (base, temp, size, 0, nmemb - 1, cmpfun);
+    }
+}