calendar: Use sensible error reporting in calendar_gregorian_to_offset().
[pspp] / src / language / expressions / helpers.c
index a0f0c0fc735f394d5c17f4cc74347f2beb44e939..ac17c1cece19ce842bde63ae9495daac3d6e0109 100644 (file)
@@ -1,3 +1,19 @@
+/* PSPP - a program for statistical analysis.
+   Copyright (C) 2008, 2010 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>. */
+
 #include <config.h>
 #include "helpers.h"
 #include <gsl/gsl_roots.h>
 
 const struct substring empty_string = {NULL, 0};
 
-static void
-expr_error (void *aux UNUSED, const char *format, ...)
-{
-  struct msg m;
-  va_list args;
-
-  m.category = MSG_SYNTAX;
-  m.severity = MSG_ERROR;
-  va_start (args, format);
-  m.text = xvasprintf (format, args);
-  va_end (args);
-
-  msg_emit (&m);
-}
-
 double
 expr_ymd_to_ofs (double year, double month, double day)
 {
   int y = year;
   int m = month;
   int d = day;
+  char *error;
+  double ofs;
 
   if (y != year || m != month || d != day)
     {
@@ -37,7 +40,13 @@ expr_ymd_to_ofs (double year, double month, double day)
       return SYSMIS;
     }
 
-  return calendar_gregorian_to_offset (y, m, d, expr_error, NULL);
+  ofs = calendar_gregorian_to_offset (y, m, d, &error);
+  if (error != NULL)
+    {
+      msg (SE, "%s", error);
+      free (error);
+    }
+  return ofs;
 }
 
 double
@@ -131,15 +140,6 @@ enum date_unit
     DATE_SECONDS
   };
 
-#ifndef HAVE_TRUNC
-/* Return X rounded toward zero. */
-static double
-trunc (double x)
-{
-  return x >= 0.0 ? floor (x) : ceil (x);
-}
-#endif /* !HAVE_TRUNC */
-
 /* Stores in *UNIT the unit whose name is NAME.
    Return success. */
 static enum date_unit
@@ -172,9 +172,11 @@ recognize_unit (struct substring name, enum date_unit *unit)
         return true;
       }
 
-  msg (SE, _("Unrecognized date unit \"%.*s\".  "
-             "Valid date units are \"years\", \"quarters\", \"months\", "
-             "\"weeks\", \"days\", \"hours\", \"minutes\", and \"seconds\"."),
+  /* TRANSLATORS: Don't translate the the actual unit names `weeks', `days' etc
+       They must remain in their original English. */
+  msg (SE, _("Unrecognized date unit `%.*s'.  "
+             "Valid date units are `years', `quarters', `months', "
+             "`weeks', `days', `hours', `minutes', and `seconds'."),
        (int) ss_length (name), ss_data (name));
   return false;
 }
@@ -323,7 +325,7 @@ recognize_method (struct substring method_name, enum date_sum_method *method)
   else
     {
       msg (SE, _("Invalid DATESUM method.  "
-                 "Valid choices are \"closest\" and \"rollover\"."));
+                 "Valid choices are `closest' and `rollover'."));
       return false;
     }
 }
@@ -335,6 +337,7 @@ add_months (double date, int months, enum date_sum_method method)
 {
   int y, m, d, yd;
   double output;
+  char *error;
 
   calendar_offset_to_gregorian (date / DAY_S, &y, &m, &d, &yd);
   y += months / 12;
@@ -354,9 +357,14 @@ add_months (double date, int months, enum date_sum_method method)
   if (method == SUM_CLOSEST && d > calendar_days_in_month (y, m))
     d = calendar_days_in_month (y, m);
 
-  output = calendar_gregorian_to_offset (y, m, d, expr_error, NULL);
+  output = calendar_gregorian_to_offset (y, m, d, &error);
   if (output != SYSMIS)
     output = (output * DAY_S) + fmod (date, DAY_S);
+  else
+    {
+      msg (SE, "%s", error);
+      free (error);
+    }
   return output;
 }
 
@@ -397,7 +405,7 @@ expr_date_sum (double date, double quantity, struct substring unit_name,
 }
 
 int
-compare_string (const struct substring *a, const struct substring *b)
+compare_string_3way (const struct substring *a, const struct substring *b)
 {
   size_t i;
 
@@ -582,14 +590,14 @@ ncdf_beta (double x, double a, double b, double lambda)
 double
 cdf_bvnor (double x0, double x1, double r)
 {
-  double z = x0 * x0 - 2. * r * x0 * x1 + x1 * x1;
+  double z = pow2 (x0) - 2. * r * x0 * x1 + pow2 (x1);
   return exp (-z / (2. * (1 - r * r))) * (2. * M_PI * sqrt (1 - r * r));
 }
 
 double
 idf_fdist (double P, double df1, double df2)
 {
-  double temp = gslextras_cdf_beta_Pinv (P, df1 / 2, df2 / 2);
+  double temp = gsl_cdf_beta_Pinv (P, df1 / 2, df2 / 2);
   return temp * df2 / ((1. - temp) * df1);
 }