From 1b47c4afe993f715c03e7392427b0b8919a26d4e Mon Sep 17 00:00:00 2001
From: Ben Pfaff <blp@gnu.org>
Date: Mon, 17 Apr 2006 03:49:48 +0000
Subject: [PATCH] Continue reforming error message support.  In this phase, we
 divide the classification of messages along "category" and "severity" axes.

---
 src/ChangeLog                      | 13 +++++
 src/data/casefile.c                |  3 +-
 src/data/data-in.c                 |  5 +-
 src/data/por-file-reader.c         |  3 +-
 src/data/sys-file-reader.c         |  3 +-
 src/language/expressions/helpers.c |  3 +-
 src/language/stats/flip.c          |  2 +-
 src/language/utilities/set.q       | 38 ++++++------
 src/libpspp/ChangeLog              | 16 +++++
 src/libpspp/message.h              | 50 +++++++++++++---
 src/message.c                      | 94 ++++++++++++------------------
 src/ui/gui/ChangeLog               | 10 ++++
 src/ui/gui/message-dialog.c        | 31 ++++------
 src/ui/gui/message-dialog.h        |  4 --
 14 files changed, 161 insertions(+), 114 deletions(-)

diff --git a/src/ChangeLog b/src/ChangeLog
index e31c7f24..cbabd2da 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,16 @@
+Sun Apr 16 20:41:10 2006  Ben Pfaff  <blp@gnu.org>
+
+	Continue reforming error message support.  In this phase, we
+	divide the classification of messages along "category" and
+	"severity" axes.
+
+	* message.c: (err_vmsg) Rewrite to deal with categories and
+	severities in a straightforward manner instead of mixing them into
+	classes.
+	[0] (puts_stderr) Removed (dead code).
+	(msg) Changed first argument from `int' to `enum msg_class'.
+	(tmsg) Ditto.
+
 Sun Apr 16 18:53:12 2006  Ben Pfaff  <blp@gnu.org>
 
 	GNU standards require "file name" instead of "filename" in
diff --git a/src/data/casefile.c b/src/data/casefile.c
index 1ae743bd..cf2d4f8d 100644
--- a/src/data/casefile.c
+++ b/src/data/casefile.c
@@ -736,7 +736,8 @@ io_error (struct casefile *cf, const char *format, ...)
       struct error e;
       va_list args;
 
-      e.class = ME;
+      e.category = MSG_GENERAL;
+      e.severity = MSG_ERROR;
       e.where.file_name = NULL;
       e.where.line_number = -1;
       e.title = NULL;
diff --git a/src/data/data-in.c b/src/data/data-in.c
index 44fd7995..1180b32b 100644
--- a/src/data/data-in.c
+++ b/src/data/data-in.c
@@ -60,8 +60,9 @@ vdls_error (const struct data_in *i, const char *format, va_list args)
   else
     ds_printf (&title, _("(columns %d-%d"), i->f1, i->f2);
   ds_printf (&title, _(", field type %s) "), fmt_to_string (&i->format));
-    
-  e.class = DE;
+
+  e.category = MSG_DATA;
+  e.severity = MSG_ERROR;
   err_location (&e.where);
   e.title = ds_c_str (&title);
 
diff --git a/src/data/por-file-reader.c b/src/data/por-file-reader.c
index 0824bb31..5b49fa5a 100644
--- a/src/data/por-file-reader.c
+++ b/src/data/por-file-reader.c
@@ -90,7 +90,8 @@ error (struct pfm_reader *r, const char *msg, ...)
   char *title;
   va_list args;
 
-  e.class = ME;
+  e.category = MSG_GENERAL;
+  e.severity = MSG_ERROR;
   e.where.file_name = NULL;
   e.where.line_number = 0;
   file_name = fh_get_file_name (r->fh);
diff --git a/src/data/sys-file-reader.c b/src/data/sys-file-reader.c
index 7ccf969b..ebf0a7b1 100644
--- a/src/data/sys-file-reader.c
+++ b/src/data/sys-file-reader.c
@@ -126,7 +126,8 @@ corrupt_msg (int class, const char *format,...)
   struct error e;
   va_list args;
 
-  e.class = class;
+  e.category = msg_class_to_category (class);
+  e.severity = msg_class_to_severity (class);
   e.where.file_name = NULL;
   e.where.line_number = 0;
   e.title = _("corrupt system file: ");
diff --git a/src/language/expressions/helpers.c b/src/language/expressions/helpers.c
index ff162147..9d0d18ca 100644
--- a/src/language/expressions/helpers.c
+++ b/src/language/expressions/helpers.c
@@ -15,7 +15,8 @@ expr_error (void *aux UNUSED, const char *format, ...)
 
   /* FIXME: we can do better about saying where the error
      occurred. */
-  e.class = SE;
+  e.category = MSG_SYNTAX;
+  e.severity = MSG_ERROR;
   err_location (&e.where);
   e.title = NULL;
 
diff --git a/src/language/stats/flip.c b/src/language/stats/flip.c
index 43d6d0f5..f2c0290c 100644
--- a/src/language/stats/flip.c
+++ b/src/language/stats/flip.c
@@ -91,7 +91,7 @@ cmd_flip (void)
 
   if (temporary != 0)
     {
-      msg (SM, _("FLIP ignores TEMPORARY.  "
+      msg (SW, _("FLIP ignores TEMPORARY.  "
                  "Temporary transformations will be made permanent."));
       cancel_temporary (); 
     }
diff --git a/src/language/utilities/set.q b/src/language/utilities/set.q
index 19a287b2..66ababdd 100644
--- a/src/language/utilities/set.q
+++ b/src/language/utilities/set.q
@@ -469,9 +469,9 @@ static void
 show_blanks (void) 
 {
   if (get_blanks () == SYSMIS)
-    msg (MM, _("BLANKS is SYSMIS."));
+    msg (MN, _("BLANKS is SYSMIS."));
   else
-    msg (MM, _("BLANKS is %g."), get_blanks ());
+    msg (MN, _("BLANKS is %g."), get_blanks ());
 
 }
 
@@ -503,7 +503,7 @@ show_cc (int idx)
   out = format_cc (cc->neg_suffix, cc->grouping, out);
   *out = '\0';
   
-  msg (MM, _("CC%c is \"%s\"."), "ABCDE"[idx], cc_string);
+  msg (MN, _("CC%c is \"%s\"."), "ABCDE"[idx], cc_string);
 }
 
 
@@ -540,61 +540,61 @@ show_cce (void)
 static void
 show_decimals (void) 
 {
-  msg (MM, _("DECIMAL is \"%c\"."), get_decimal ());
+  msg (MN, _("DECIMAL is \"%c\"."), get_decimal ());
 }
 
 static void
 show_endcmd (void) 
 {
-  msg (MM, _("ENDCMD is \"%c\"."), get_endcmd ());
+  msg (MN, _("ENDCMD is \"%c\"."), get_endcmd ());
 }
 
 static void
 show_format (void) 
 {
-  msg (MM, _("FORMAT is %s."), fmt_to_string (get_format ()));
+  msg (MN, _("FORMAT is %s."), fmt_to_string (get_format ()));
 }
 
 static void
 show_length (void) 
 {
-  msg (MM, _("LENGTH is %d."), get_viewlength ());
+  msg (MN, _("LENGTH is %d."), get_viewlength ());
 }
 
 static void
 show_mxerrs (void) 
 {
-  msg (MM, _("MXERRS is %d."), get_mxerrs ());
+  msg (MN, _("MXERRS is %d."), get_mxerrs ());
 }
 
 static void
 show_mxloops (void) 
 {
-  msg (MM, _("MXLOOPS is %d."), get_mxloops ());
+  msg (MN, _("MXLOOPS is %d."), get_mxloops ());
 }
 
 static void
 show_mxwarns (void) 
 {
-  msg (MM, _("MXWARNS is %d."), get_mxwarns ());
+  msg (MN, _("MXWARNS is %d."), get_mxwarns ());
 }
 
 static void
 show_scompression (void) 
 {
   if (get_scompression ())
-    msg (MM, _("SCOMPRESSION is ON."));
+    msg (MN, _("SCOMPRESSION is ON."));
   else
-    msg (MM, _("SCOMPRESSION is OFF."));
+    msg (MN, _("SCOMPRESSION is OFF."));
 }
 
 static void
 show_undefined (void) 
 {
   if (get_undefined ())
-    msg (MM, _("UNDEFINED is WARN."));
+    msg (MN, _("UNDEFINED is WARN."));
   else
-    msg (MM, _("UNDEFINED is NOWARN."));
+    msg (MN, _("UNDEFINED is NOWARN."));
 }
 
 static void
@@ -602,15 +602,15 @@ show_weight (void)
 {
   struct variable *var = dict_get_weight (default_dict);
   if (var == NULL)
-    msg (MM, _("WEIGHT is off."));
+    msg (MN, _("WEIGHT is off."));
   else
-    msg (MM, _("WEIGHT is variable %s."), var->name);
+    msg (MN, _("WEIGHT is variable %s."), var->name);
 }
 
 static void
 show_width (void) 
 {
-  msg (MM, _("WIDTH is %d."), get_viewwidth ());
+  msg (MN, _("WIDTH is %d."), get_viewwidth ());
 }
 
 struct show_sbc 
@@ -661,13 +661,13 @@ show_all_cc (void)
 static void
 show_warranty (void) 
 {
-  msg (MM, lack_of_warranty);
+  msg (MN, lack_of_warranty);
 }
 
 static void
 show_copying (void) 
 {
-  msg (MM, copyleft);
+  msg (MN, copyleft);
 }
 
 int
diff --git a/src/libpspp/ChangeLog b/src/libpspp/ChangeLog
index 2c80db58..88955ac4 100644
--- a/src/libpspp/ChangeLog
+++ b/src/libpspp/ChangeLog
@@ -1,3 +1,19 @@
+Sun Apr 16 20:43:35 2006  Ben Pfaff  <blp@gnu.org>
+
+	Continue reforming error message support.  In this phase, we
+	divide the classification of messages along "category" and
+	"severity" axes.
+
+	* message.h: (enum msg_class) Named this set of enumerations.
+	(enum msg_category) New enum: MSG_GENERAL, MSG_SYNTAX, MSG_DATA.
+	(enum msg_severity) New enum: MSG_ERROR, MSG_WARNING, MSG_NOTE.
+	(msg_class_to_category) New inline function.
+	(msg_class_to_severity) New inline function.
+	(msg_class_from_category_and_severity) New inline function.
+	(struct error) Removed `class' member, added `category',
+	`severity'.  Updated all users of this struct to use the new
+	members.
+
 Sun Apr 16 20:33:19 2006  Ben Pfaff  <blp@gnu.org>
 
 	* str.c (ds_vprintf): Don't try to write into the string if it is
diff --git a/src/libpspp/message.h b/src/libpspp/message.h
index 3422a6ed..9dae1e40 100644
--- a/src/libpspp/message.h
+++ b/src/libpspp/message.h
@@ -25,14 +25,49 @@
 #include "compiler.h"
 
 /* Message classes. */
-enum
+enum msg_class
   {
-    SE, SW, SM,			/* Script error/warning/message. */
-    DE, DW,			/* Data-file error/warning. */
-    ME, MW, MM,			/* General error/warning/message. */
+    ME, MW, MN,			/* General error/warning/note. */
+    SE, SW, SN,			/* Script error/warning/note. */
+    DE, DW, DN,			/* Data-file error/note. */
     MSG_CLASS_CNT,
   };
 
+/* What kind of message is this? */
+enum msg_category 
+  {
+    MSG_GENERAL,        /* General info. */
+    MSG_SYNTAX,         /* Messages that relate to syntax files. */
+    MSG_DATA            /* Messages that relate to data files. */
+  };
+
+/* How important a condition is it? */
+enum msg_severity 
+  {
+    MSG_ERROR,
+    MSG_WARNING,
+    MSG_NOTE
+  };
+
+static inline enum msg_category
+msg_class_to_category (enum msg_class class) 
+{
+  return class / 3;
+}
+
+static inline enum msg_severity
+msg_class_to_severity (enum msg_class class) 
+{
+  return class % 3;
+}
+
+static inline enum msg_class
+msg_class_from_category_and_severity (enum msg_category category,
+                                      enum msg_severity severity) 
+{
+  return category * 3 + severity;
+}
+
 /* A file location.  */
 struct file_locator
   {
@@ -43,7 +78,8 @@ struct file_locator
 /* An error message. */
 struct error
   {
-    int class;			/* One of the classes above. */
+    enum msg_category category; /* Message category. */
+    enum msg_severity severity; /* Message severity. */
     struct file_locator where;	/* File location, or (NULL, -1). */
     const char *title;		/* Special text inserted if not null. */
   };
@@ -61,9 +97,9 @@ extern int err_already_flagged;
 extern int err_verbosity;
 
 /* Functions. */
-void msg (int class, const char *format, ...)
+void msg (enum msg_class, const char *format, ...)
      PRINTF_FORMAT (2, 3);
-void tmsg (int class, const char *title, const char *format, ...)
+void tmsg (enum msg_class, const char *title, const char *format, ...)
      PRINTF_FORMAT (3, 4);
 
 void verbose_msg (int level, const char *format, ...)
diff --git a/src/message.c b/src/message.c
index e6a8f76b..b96cdb0d 100644
--- a/src/message.c
+++ b/src/message.c
@@ -45,17 +45,18 @@ int err_verbosity;
 
 static char *command_name;
 
-/* Fairly common public functions. */
+/* Public functions. */
 
 /* Writes error message in CLASS, with title TITLE and text FORMAT,
    formatted with printf, to the standard places. */
 void
-tmsg (int class, const char *title, const char *format, ...)
+tmsg (enum msg_class class, const char *title, const char *format, ...)
 {
   struct error e;
   va_list args;
 
-  e.class = class;
+  e.category = msg_class_to_category (class);
+  e.severity = msg_class_to_severity (class);
   err_location (&e.where);
   e.title = title;
 
@@ -67,12 +68,13 @@ tmsg (int class, const char *title, const char *format, ...)
 /* Writes error message in CLASS, with text FORMAT, formatted with
    printf, to the standard places. */
 void
-msg (int class, const char *format, ...)
+msg (enum msg_class class, const char *format, ...)
 {
   struct error e;
   va_list args;
 
-  e.class = class;
+  e.category = msg_class_to_category (class);
+  e.severity = msg_class_to_severity (class);
   err_location (&e.where);
   e.title = NULL;
 
@@ -104,12 +106,12 @@ void
 err_check_count (void)
 {
   if (get_errorbreak() && err_error_count)
-    msg (MM, _("Terminating execution of syntax file due to error."));
+    msg (MN, _("Terminating execution of syntax file due to error."));
   else if (err_error_count > get_mxerrs() )
-    msg (MM, _("Errors (%d) exceeds limit (%d)."),
+    msg (MN, _("Errors (%d) exceeds limit (%d)."),
 	 err_error_count, get_mxerrs());
   else if (err_error_count + err_warning_count > get_mxwarns() )
-    msg (MM, _("Warnings (%d) exceed limit (%d)."),
+    msg (MN, _("Warnings (%d) exceed limit (%d)."),
 	 err_error_count + err_warning_count, get_mxwarns() );
   else
     return;
@@ -141,42 +143,37 @@ err_done (void)
 void
 err_vmsg (const struct error *e, const char *format, va_list args)
 {
-  /* Class flags. */
-  enum
+  struct category 
     {
-      ERR_IN_PROCEDURE = 01,	/* 1=Display name of current procedure. */
-      ERR_WITH_FILE = 02,	/* 1=Display file name and line number. */
+      bool show_command_name;   /* Show command name with error? */
+      bool show_file_location;  /* Show syntax file location? */
     };
 
-  /* Describes one class of error. */
-  struct error_class
+  static const struct category categories[] = 
     {
-      int flags;		/* Zero or more of ERR_*. */
-      int *count;		/* Counting category. */
-      const char *banner;	/* Banner. */
+      {false, false},           /* MSG_GENERAL. */
+      {true, true},             /* MSG_SYNTAX. */
+      {false, true},            /* MSG_DATA. */
     };
 
-  static const struct error_class error_classes[MSG_CLASS_CNT] =
+  struct severity 
     {
-      {3, &err_error_count, N_("error")},	/* SE */
-      {3, &err_warning_count, N_("warning")},	/* SW */
-      {3, NULL, N_("note")},			/* SM */
-
-      {2, &err_error_count, N_("error")},	/* DE */
-      {2, &err_warning_count, N_("warning")},	/* DW */
-
-      {0, &err_error_count, N_("error")},	/* ME */
-      {0, &err_warning_count, N_("warning")},	/* MW */
-      {0, NULL, N_("note")},			/* MM */
+      const char *name;         /* How to identify this severity. */
+      int *count;               /* Number of msgs with this severity so far. */
+    };
+  
+  static struct severity severities[] = 
+    {
+      {N_("error"), &err_error_count},          /* MSG_ERROR. */
+      {N_("warning"), &err_warning_count},      /* MSG_WARNING. */
+      {NULL, NULL},                             /* MSG_NOTE. */
     };
 
-  struct string msg;
+  const struct category *category = &categories[e->category];
+  const struct severity *severity = &severities[e->severity];
+  struct string msg = DS_INITIALIZER;
 
-  assert (e->class >= 0 && e->class < MSG_CLASS_CNT);
-  assert (format != NULL);
-  
-  ds_init (&msg, 64);
-  if (e->where.file_name && (error_classes[e->class].flags & ERR_WITH_FILE))
+  if (category->show_file_location && e->where.file_name)
     {
       ds_printf (&msg, "%s:", e->where.file_name);
       if (e->where.line_number != -1)
@@ -184,16 +181,13 @@ err_vmsg (const struct error *e, const char *format, va_list args)
       ds_putc (&msg, ' ');
     }
 
-  ds_printf (&msg, "%s: ", gettext (error_classes[e->class].banner));
+  if (severity->name != NULL)
+    ds_printf (&msg, "%s: ", gettext (severity->name));
   
-  {
-    int *count = error_classes[e->class].count;
-    if (count)
-      (*count)++;
-  }
+  if (severity->count != NULL)
+    ++*severity->count;
   
-  if (command_name != NULL
-      && (error_classes[e->class].flags & ERR_IN_PROCEDURE))
+  if (category->show_command_name && command_name != NULL)
     ds_printf (&msg, "%s: ", command_name);
 
   if (e->title)
@@ -202,11 +196,7 @@ err_vmsg (const struct error *e, const char *format, va_list args)
   ds_vprintf (&msg, format, args);
 
   /* FIXME: Check set_messages and set_errors to determine where to
-     send errors and messages.
-
-     Please note that this is not trivial.  We have to avoid an
-     infinite loop in reporting errors that originate in the output
-     section. */
+     send errors and messages. */
   dump_message (ds_c_str (&msg), 8, puts_stdout, get_viewwidth());
 
   ds_destroy (&msg);
@@ -214,16 +204,6 @@ err_vmsg (const struct error *e, const char *format, va_list args)
 
 /* Private functions. */
 
-#if 0
-/* Write S followed by a newline to stderr. */
-static void
-puts_stderr (const char *s)
-{
-  fputs (s, stderr);
-  fputc ('\n', stderr);
-}
-#endif
-
 /* Write S followed by a newline to stdout. */
 static void
 puts_stdout (const char *s)
diff --git a/src/ui/gui/ChangeLog b/src/ui/gui/ChangeLog
index f55f6eb0..c60dee15 100644
--- a/src/ui/gui/ChangeLog
+++ b/src/ui/gui/ChangeLog
@@ -1,3 +1,13 @@
+Sun Apr 16 20:45:35 2006  Ben Pfaff  <blp@gnu.org>
+
+	Continue reforming error message support.  In this phase, we
+	divide the classification of messages along "category" and
+	"severity" axes.
+
+	* message-dialog.c: (vmsg) Use severity and category in
+	straightforward fashion instead of the less obvious "class".
+	(err_vmsg) Construct class before passing along to vmsg().
+
 Sun Apr 16 16:06:54 2006  Ben Pfaff  <blp@gnu.org>
 
 	Continue reforming error message support.  In this phase, we get
diff --git a/src/ui/gui/message-dialog.c b/src/ui/gui/message-dialog.c
index 693db49f..c5928d35 100644
--- a/src/ui/gui/message-dialog.c
+++ b/src/ui/gui/message-dialog.c
@@ -50,41 +50,31 @@ vmsg(int klass, const char *fmt, va_list args)
 		    
   gint message_type;
 
-  switch (klass)
+  switch (msg_class_to_severity (klass))
     {
-    case SE:
-    case DE:
-    case ME:
+    case MSG_ERROR:
       message_type = GTK_MESSAGE_ERROR;
       break;
-    case SW:
-    case DW:
-    case MW:
+    case MSG_WARNING:
       message_type = GTK_MESSAGE_WARNING;
       break;
-    case SM:
-    case MM:
+    case MSG_NOTE:
     default:
       message_type = GTK_MESSAGE_INFO;
       break;
     };
   
-  switch (klass) 
+  switch (msg_class_to_category (klass)) 
     {
-    case SE:
-    case SW:
-    case SM:
+    case MSG_SYNTAX:
       msg = g_strdup(_("Script Error"));
       break;
 
-    case DE:
-    case DW:
+    case MSG_DATA:
       msg = g_strdup(_("Data File Error"));
       break;
 
-    case ME:
-    case MW:
-    case MM:
+    case MSG_GENERAL:
     default:
       msg = g_strdup(_("PSPP Error"));
       break;
@@ -113,7 +103,7 @@ vmsg(int klass, const char *fmt, va_list args)
 
 
 void 
-msg(int klass, const char *fmt, ...)
+msg(enum msg_class klass, const char *fmt, ...)
 {
   va_list ap;
   va_start(ap, fmt);
@@ -125,7 +115,8 @@ msg(int klass, const char *fmt, ...)
 void
 err_vmsg (const struct error *e, const char *format, va_list args)
 {
-  vmsg(e->class, format, args);
+  vmsg(msg_class_from_category_and_severity (e->category, e->severity),
+       format, args);
 }
 
 
diff --git a/src/ui/gui/message-dialog.h b/src/ui/gui/message-dialog.h
index 3b85e60f..66a33633 100644
--- a/src/ui/gui/message-dialog.h
+++ b/src/ui/gui/message-dialog.h
@@ -24,8 +24,4 @@
 
 #include <libpspp/message.h>
 
-void vmsg(int klass, const char *fmt, va_list args);
-void  msg(int klass, const char *fmt, ...);
-
-
 #endif
-- 
2.30.2