]> sjero.net Git - wget/blobdiff - src/init.c
[svn] Remove VERY_LONG_TYPE; use LARGE_INT instead. Remove special code
[wget] / src / init.c
index 0cd65ae5f1c6ce3c8ab3dff9653b47dd2d86fa83..50c66c447a7c1d281d0ac40340541dbd4736bb97 100644 (file)
@@ -84,6 +84,7 @@ static int enable_tilde_expansion;
 
 CMD_DECLARE (cmd_boolean);
 CMD_DECLARE (cmd_bytes);
+CMD_DECLARE (cmd_bytes_large);
 CMD_DECLARE (cmd_directory_vector);
 CMD_DECLARE (cmd_lockable_boolean);
 CMD_DECLARE (cmd_number);
@@ -184,7 +185,7 @@ static struct {
   { "proxypasswd",     &opt.proxy_passwd,      cmd_string },
   { "proxyuser",       &opt.proxy_user,        cmd_string },
   { "quiet",           &opt.quiet,             cmd_boolean },
-  { "quota",           &opt.quota,             cmd_bytes },
+  { "quota",           &opt.quota,             cmd_bytes_large },
   { "randomwait",      &opt.random_wait,       cmd_boolean },
   { "readtimeout",     &opt.read_timeout,      cmd_time },
   { "reclevel",                &opt.reclevel,          cmd_number_inf },
@@ -849,60 +850,45 @@ cmd_directory_vector (const char *com, const char *val, void *closure)
 
 static int simple_atof PARAMS ((const char *, const char *, double *));
 
-/* Parse VAL as a number and set its value to CLOSURE (which should
-   point to a long int).
-
-   By default, the value is assumed to be in bytes.  If "K", "M", or
-   "G" are appended, the value is multiplied with 1<<10, 1<<20, or
-   1<<30, respectively.  Floating point values are allowed and are
-   cast to integer before use.  The idea is to be able to use things
-   like 1.5k instead of "1536".
-
-   The string "inf" is returned as 0.
-
-   In case of error, 0 is returned and memory pointed to by CLOSURE
-   remains unmodified.  */
+/* Enginge for cmd_bytes and cmd_bytes_large: converts a string such
+   as "100k" or "2.5G" to a floating point number.  */
 
 static int
-cmd_bytes (const char *com, const char *val, void *closure)
+parse_bytes_helper (const char *val, double *result)
 {
-  long mult;
-  double number;
+  double number, mult;
   const char *end = val + strlen (val);
 
   /* Check for "inf".  */
   if (0 == strcmp (val, "inf"))
     {
-      *(long *)closure = 0;
+      *result = 0;
       return 1;
     }
 
   /* Strip trailing whitespace.  */
   while (val < end && ISSPACE (end[-1]))
     --end;
-
   if (val == end)
-    {
-    err:
-      fprintf (stderr, _("%s: %s: Invalid byte value `%s'\n"),
-              exec_name, com, val);
-      return 0;
-    }
+    return 0;
 
   switch (TOLOWER (end[-1]))
     {
     case 'k':
-      --end, mult = 1L<<10;
+      --end, mult = 1024.0;
       break;
     case 'm':
-      --end, mult = 1L<<20;
+      --end, mult = 1048576.0;
       break;
     case 'g':
-      --end, mult = 1L<<30;
+      --end, mult = 1073741824.0;
+      break;
+    case 't':
+      --end, mult = 1099511627776.0;
       break;
     default:
-      /* Not a recognized suffix: assume it belongs to the number.
-        (If not, atof simple_atof will raise an error.)  */
+      /* Not a recognized suffix: assume it's a digit.  (If not,
+        simple_atof will raise an error.)  */
       mult = 1;
     }
 
@@ -912,12 +898,59 @@ cmd_bytes (const char *com, const char *val, void *closure)
   while (val < end && ISSPACE (end[-1]))
     --end;
   if (val == end)
-    goto err;
+    return 0;
 
   if (!simple_atof (val, end, &number))
-    goto err;
+    return 0;
+
+  *result = number * mult;
+  return 1;
+}
 
-  *(long *)closure = (long)(number * mult);
+/* Parse VAL as a number and set its value to CLOSURE (which should
+   point to a long int).
+
+   By default, the value is assumed to be in bytes.  If "K", "M", or
+   "G" are appended, the value is multiplied with 1<<10, 1<<20, or
+   1<<30, respectively.  Floating point values are allowed and are
+   cast to integer before use.  The idea is to be able to use things
+   like 1.5k instead of "1536".
+
+   The string "inf" is returned as 0.
+
+   In case of error, 0 is returned and memory pointed to by CLOSURE
+   remains unmodified.  */
+
+static int
+cmd_bytes (const char *com, const char *val, void *closure)
+{
+  double byte_value;
+  if (!parse_bytes_helper (val, &byte_value))
+    {
+      fprintf (stderr, _("%s: %s: Invalid byte value `%s'\n"),
+              exec_name, com, val);
+      return 0;
+    }
+  *(long *)closure = (long)byte_value;
+  return 1;
+}
+
+/* Like cmd_bytes, but CLOSURE is interpreted as a pointer to
+   LARGE_INT.  It works by converting the string to double, therefore
+   working with values up to 2^53-1 without loss of precision.  This
+   value (8192 TB) is large enough to serve for a while.  */
+
+static int
+cmd_bytes_large (const char *com, const char *val, void *closure)
+{
+  double byte_value;
+  if (!parse_bytes_helper (val, &byte_value))
+    {
+      fprintf (stderr, _("%s: %s: Invalid byte value `%s'\n"),
+              exec_name, com, val);
+      return 0;
+    }
+  *(LARGE_INT *)closure = (LARGE_INT)byte_value;
   return 1;
 }