summaryrefslogtreecommitdiff
path: root/comm/error.cc
diff options
context:
space:
mode:
authorchatty1993-04-07 11:50:31 +0000
committerchatty1993-04-07 11:50:31 +0000
commitba066c34dde204aa192d03a23a81356374d93731 (patch)
tree39391f6235d2cf8a59a0634ac5ea430cdd21f5d4 /comm/error.cc
parent05ab076e1c2a9ca16472f9a6b47b8d22914b3783 (diff)
downloadivy-league-ba066c34dde204aa192d03a23a81356374d93731.zip
ivy-league-ba066c34dde204aa192d03a23a81356374d93731.tar.gz
ivy-league-ba066c34dde204aa192d03a23a81356374d93731.tar.bz2
ivy-league-ba066c34dde204aa192d03a23a81356374d93731.tar.xz
Initial revision
Diffstat (limited to 'comm/error.cc')
-rw-r--r--comm/error.cc261
1 files changed, 261 insertions, 0 deletions
diff --git a/comm/error.cc b/comm/error.cc
new file mode 100644
index 0000000..fc02eb9
--- /dev/null
+++ b/comm/error.cc
@@ -0,0 +1,261 @@
+/*
+ * The Unix Channel
+ *
+ * by Michel Beaudouin-Lafon
+ *
+ * Copyright 1990-1993
+ * Laboratoire de Recherche en Informatique (LRI)
+ *
+ * Error management
+ *
+ * $Id$
+ * $CurLog$
+ */
+
+#include "error.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdio.h>
+
+/*?class UchERROR
+The set of global functions described here are designed to handle errors.
+An error has a type, an origin, and a message.
+The type defines how the error is handled.
+The origin and the message are used to generate the error message.
+The origin is usually the function name where the error occurred.
+A log file may be defined for storing all error messages, in addition to the normal
+notification mechanism.
+
+Handling the error is a three steps process:
+first the error string is generated, then the error is emitted by a user-defined error handler,
+and finally the way the program continues is determined from the error type.
+These types are described by the following values (enumerated type \typ{^{errtype}}):
+\index{errtype :: ErrNone}\index{errtype :: ErrLog}\index{errtype :: ErrWarn}
+\index{errtype :: ErrAbort}\index{errtype :: ErrExit}\index{errtype :: ErrFatal}
+\index{errtype :: ErrUsage}
+\begin{itemize}
+\item \var{ErrNone} is not an error: the handler is not called and the program continues;
+\item \var{ErrLog} is an error that is only logged to the log file: the handler is not called and the program continues;
+\item \var{ErrWarn} is a warning: the handler is called and the program then continues;
+\item \var{ErrAbort} handles the error and calls \fun{abort};
+\item \var{ErrExit} handles the error and calls \fun{exit(0)};
+\item \var{ErrFatal} handles the error and calls \fun{exit(1)};
+\item \var{ErrUsage} handles the error and calls \fun{exit(1)};
+\var{ErrUsage} is different from \var{ErrFatal} in that the generated error message
+is not the same (see \fun{MakeErrorString}).
+\end{itemize}
+
+The type of an error handler is the following:
+\index{ErrorHandler}
+\begin{ccode}
+typedef errtype (*ErrorHandler) (errtype, const char* who, const char* what, const char* msg);
+\end{ccode}
+?*/
+
+// static data for error handling: message table and default handler
+//
+char* ErrorTable [] = {
+ "Subclass should implement virtual member", // ErrShouldImplement
+};
+
+static char ProgName [128], LogFile [128];
+static bool LogOn =FALSE;
+
+static errtype
+DefaultHandler (errtype how, const char* /*who*/, const char* /*what*/, const char* msg)
+{
+ write (2, msg, strlen (msg));
+ return how;
+}
+
+static ErrorHandler Handler = DefaultHandler;
+
+// main function for handling errors
+//
+static bool
+HandleError (errtype how, const char* who, const char* what)
+{
+ if (how == ErrNone)
+ return TRUE;
+
+ char *msg = MakeErrorString (how, who, what);
+
+ if (how >= ErrLog && LogOn) {
+ LogMessage (msg);
+ if (how == ErrLog)
+ return TRUE;
+ }
+
+ how = (*Handler) (how, who, what, msg);
+
+ switch (how) {
+ case ErrNone:
+ return TRUE;
+ case ErrLog:
+ case ErrWarn:
+ break;
+ case ErrAbort:
+ write (2, "aborting\n", 9);
+ abort ();
+ break;
+ case ErrExit:
+ exit (0);
+ break;
+ case ErrUsage:
+ case ErrFatal:
+ exit (1);
+ break;
+ }
+ return FALSE;
+}
+
+// public functions:
+// register program name, cleanup function, log file
+// change error handler
+// error functions
+//
+
+/*?
+Set the program name, that is used to label each output message.
+This usually called from \fun{main} with \com{argv[0]} as argument.
+?*/
+void
+ProgramName (const char* name)
+{
+ if (name)
+ strncpy (ProgName, name, sizeof (ProgName) -1);
+ else
+ ProgName [0] = 0;
+}
+
+/*?
+Set the log file name.
+All messages are appended to the logfile.
+If \var{reset} is TRUE, the file is cleared.
+NOTE : logging is not currently implemented.
+?*/
+void
+LogfileName (const char* file, bool reset)
+{
+ if (file) {
+ strncpy (LogFile, file, sizeof (LogFile) -1);
+ LogOn = TRUE;
+ if (reset) {
+ // to do: clear logfile
+ }
+ } else
+ LogOn = FALSE;
+}
+
+/*?nodoc?*/
+void
+CleanUp (CleanUpProc)
+{
+ // to do: register function
+}
+
+/*?
+Append a message to the logfile, if one has been specified.
+NOTE : logging is not currently implemented.
+?*/
+void
+LogMessage (const char*)
+{
+ // to be done
+}
+
+/*?
+Build an error message from the type of error, the place where the error occurred,
+and the error message itself, with the following format:\\
+``\com{ [program\_name :] [fatal error in]}\var{who}\com{: }\var{what}''\\
+When \var{how} is \var{ErrUsage}, the format is\\
+``\com{ usage: program\_name}\var{what}''.\\
+The string returned is the address of a static buffer that is overwritten
+each time this function is called.
+?*/
+char*
+MakeErrorString (errtype how, const char* who, const char* what)
+{
+ static char errmsg [1024];
+
+ if (how == ErrUsage)
+ sprintf (errmsg, "usage: %s %s\n", ProgName, what);
+ else
+ sprintf (errmsg, "%s%s%s%s: %s\n",
+ ProgName,
+ ProgName [0] ? ": " : "",
+ how >= ErrAbort ? "fatal error in " : "",
+ who,
+ what);
+ return errmsg;
+}
+
+/*?
+Change the error handler.
+The error handler is called each time an error is emitted.
+It is called with four arguments:
+the error type, the error source, the error message,
+and the error string as returned by \fun{MakeErrorString}.
+It should return an error type (usually the first argument) that determines
+what happens next: nothing, logging to a file, aborting, or exiting.
+The default error handler can be reset by passing the argument 0.
+The default error handler writes the error string to the standard error,
+and returns its first argument.
+?*/
+ErrorHandler
+SetErrorHandler (ErrorHandler h)
+{
+ ErrorHandler old = Handler;
+ if (! h)
+ h = DefaultHandler;
+ Handler = h;
+ return old;
+}
+
+/*?
+Emit an error of type \var{how}, from function \var{who}, with message \var{what}.
+?*/
+void
+Error (errtype how, const char* who, const char* what)
+{
+ HandleError (how, who, what);
+}
+
+/*?
+Emit a system error of type \var{how}, from function \var{who}.
+The message is retrieved from the value of the global variable \var{errno}.
+Thus, this function should be used after system calls that set \var{errno}.
+\var{exc1} and \var{exc2}, if non negative, are error codes (values of \var{errno}) to be ignored:
+if the current error code is one of these, the function returns FALSE.
+This is useful for instance to ignore interrupted system calls:
+\begin{ccode}
+ #include <errno.h>
+ n = read (...);
+ if (n < 0)
+ SysError (ErrWarn, "read", EINTR);
+\end{ccode}
+?*/
+bool
+SysError (errtype how, const char* who, int exc1, int exc2)
+{
+ extern int errno;
+ extern int sys_nerr;
+ extern char* sys_errlist [];
+ char* msg;
+ char defmsg [80];
+
+ if (! errno || errno == exc1 || errno == exc2)
+ return FALSE;
+
+ if (errno >= sys_nerr)
+ sprintf (msg = defmsg, "system error code %d", errno);
+ else
+ if (errno == 0)
+ msg = "internal error";
+ else
+ msg = sys_errlist [errno];
+ return HandleError (how, who, msg);
+}
+