calendar: Use sensible error reporting in calendar_gregorian_to_offset().
authorBen Pfaff <blp@cs.stanford.edu>
Sat, 18 Sep 2010 00:10:44 +0000 (17:10 -0700)
committerBen Pfaff <blp@cs.stanford.edu>
Fri, 24 Sep 2010 04:13:11 +0000 (21:13 -0700)
src/data/calendar.c
src/data/calendar.h
src/data/data-in.c
src/data/psql-reader.c
src/language/expressions/helpers.c

index eb9e67250a733394739f997ab1c7b504627b1b50..ef6aa6755e4a922171fa863020091cf8094e5405 100644 (file)
@@ -52,8 +52,7 @@ raw_gregorian_to_offset (int y, int m, int d)
    Gregorian calendar.  Returns SYSMIS for dates before 14 Oct
    1582. */
 double
-calendar_gregorian_to_offset (int y, int m, int d,
-                              calendar_error_func *error, void *aux)
+calendar_gregorian_to_offset (int y, int m, int d, char **errorp)
 {
   /* Normalize year. */
   if (y >= 0 && y < 100)
@@ -78,7 +77,9 @@ calendar_gregorian_to_offset (int y, int m, int d,
         }
       else
         {
-          error (aux, _("Month %d is not in acceptable range of 0 to 13."), m);
+          if (errorp != NULL)
+            *errorp = xasprintf (_("Month %d is not in acceptable range of "
+                                   "0 to 13."), m);
           return SYSMIS;
         }
     }
@@ -86,19 +87,24 @@ calendar_gregorian_to_offset (int y, int m, int d,
   /* Normalize day. */
   if (d < 0 || d > 31)
     {
-      error (aux, _("Day %d is not in acceptable range of 0 to 31."), d);
+      if (errorp != NULL)
+        *errorp = xasprintf (_("Day %d is not in acceptable range of "
+                               "0 to 31."), d);
       return SYSMIS;
     }
 
   /* Validate date. */
   if (y < 1582 || (y == 1582 && (m < 10 || (m == 10 && d < 15))))
     {
-      error (aux, _("Date %04d-%d-%d is before the earliest acceptable "
-                    "date of 1582-10-15."), y, m, d);
+      if (errorp != NULL)
+        *errorp = xasprintf (_("Date %04d-%d-%d is before the earliest "
+                               "acceptable date of 1582-10-15."), y, m, d);
       return SYSMIS;
     }
 
   /* Calculate offset. */
+  if (errorp != NULL)
+    *errorp = NULL;
   return raw_gregorian_to_offset (y, m, d);
 }
 
index 06d2fd3a49b0f350b1015e05fc8fa41223421304..5535690447ee1c55f24dc3383bca27ddb6aa8931 100644 (file)
@@ -1,10 +1,7 @@
 #ifndef CALENDAR_H
 #define CALENDAR_H 1
 
-typedef void calendar_error_func (void *aux, const char *, ...);
-
-double calendar_gregorian_to_offset (int y, int m, int d,
-                                     calendar_error_func *, void *aux);
+double calendar_gregorian_to_offset (int y, int m, int d, char **errorp);
 void calendar_offset_to_gregorian (int ofs, int *y, int *m, int *d, int *yd);
 int calendar_offset_to_year (int ofs);
 int calendar_offset_to_month (int ofs);
index 35a725d577d08ff50711c37b10fb8b2f021bb202..2b842b8dcd93eb71fd5324eda0c4d7bd7c8c5c8c 100644 (file)
@@ -74,8 +74,6 @@ typedef bool data_in_parser_func (struct data_in *);
         static data_in_parser_func parse_##METHOD;
 #include "format.def"
 
-static void vdata_warning (const struct data_in *, const char *, va_list)
-     PRINTF_FORMAT (2, 0);
 static void data_warning (const struct data_in *, const char *, ...)
      PRINTF_FORMAT (2, 3);
 
@@ -1019,19 +1017,6 @@ parse_weekday (struct data_in *i, long *weekday)
 \f
 /* Date & time formats. */
 
-/* Helper function for passing to
-   calendar_gregorian_to_offset. */
-static void
-calendar_error (void *i_, const char *format, ...)
-{
-  struct data_in *i = i_;
-  va_list args;
-
-  va_start (args, format);
-  vdata_warning (i, format, args);
-  va_end (args);
-}
-
 /* Parses WKDAY format. */
 static bool
 parse_WKDAY (struct data_in *i)
@@ -1162,10 +1147,16 @@ parse_date (struct data_in *i)
 
   if (year != INT_MIN)
     {
-      double ofs = calendar_gregorian_to_offset (year, month, day,
-                                                 calendar_error, i);
+      char *error;
+      double ofs;
+
+      ofs = calendar_gregorian_to_offset (year, month, day, &error);
       if (ofs == SYSMIS)
-        return false;
+        {
+          data_warning (i, "%s", error);
+          free (error);
+          return false;
+        }
       date = (yday - 1 + ofs) * 60. * 60. * 24.;
     }
   else
@@ -1177,18 +1168,21 @@ parse_date (struct data_in *i)
 \f
 /* Utility functions. */
 
-/* Outputs FORMAT with the given ARGS as a warning for input
-   I. */
+/* Outputs FORMAT with as a warning for input I. */
 static void
-vdata_warning (const struct data_in *i, const char *format, va_list args)
+data_warning (const struct data_in *i, const char *format, ...)
 {
+  va_list args;
   struct msg m;
   struct string text;
 
   ds_init_empty (&text);
   ds_put_char (&text, '(');
   ds_put_format (&text, _("%s field) "), fmt_name (i->format));
+
+  va_start (args, format);
   ds_put_vformat (&text, format, args);
+  va_end (args);
 
   m.category = MSG_C_DATA;
   m.severity = MSG_S_WARNING;
@@ -1201,18 +1195,6 @@ vdata_warning (const struct data_in *i, const char *format, va_list args)
   msg_emit (&m);
 }
 
-/* Outputs FORMAT with the given ARGS as a warning for input
-   I. */
-static void
-data_warning (const struct data_in *i, const char *format, ...)
-{
-  va_list args;
-
-  va_start (args, format);
-  vdata_warning (i, format, args);
-  va_end (args);
-}
-
 /* Apply implied decimal places to output. */
 static void
 apply_implied_decimals (struct data_in *i)
index b86cf4ed6cbdf483fdc861db0e644514537a0d90..76b4674dc9d914cabaadce71aef6512be050e683 100644 (file)
@@ -1,5 +1,5 @@
 /* PSPP - a program for statistical analysis.
-   Copyright (C) 2008, 2009 Free Software Foundation, Inc.
+   Copyright (C) 2008, 2009, 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
@@ -286,8 +286,7 @@ psql_open_reader (struct psql_read_info *info, struct dictionary **dict)
        }
     }
 
-  r->postgres_epoch =
-    calendar_gregorian_to_offset (2000, 1, 1, NULL, NULL);
+  r->postgres_epoch = calendar_gregorian_to_offset (2000, 1, 1, NULL);
 
 
   /* Create the dictionary and populate it */
index 08f787fea2f30c14099df3c82808623b2e886e30..ac17c1cece19ce842bde63ae9495daac3d6e0109 100644 (file)
 
 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_C_SYNTAX;
-  m.severity = MSG_S_ERROR;
-  va_start (args, format);
-  m.text = xvasprintf (format, args);
-  m.where.file_name = NULL;
-  m.where.line_number = 0;
-  m.where.first_column = 0;
-  m.where.last_column = 0;
-  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)
     {
@@ -57,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
@@ -348,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;
@@ -367,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;
 }