Update copyright date; remove old CVS keyword
[ctsim.git] / libctsupport / syserror.cpp
1 /*****************************************************************************
2 **  This is part of the CTSim program
3 **  Copyright (c) 1983-2009 Kevin Rosenberg
4 **
5 **  This program is free software; you can redistribute it and/or modify
6 **  it under the terms of the GNU General Public License (version 2) as
7 **  published by the Free Software Foundation.
8 **
9 **  This program is distributed in the hope that it will be useful,
10 **  but WITHOUT ANY WARRANTY; without even the implied warranty of
11 **  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 **  GNU General Public License for more details.
13 **
14 **  You should have received a copy of the GNU General Public License
15 **  along with this program; if not, write to the Free Software
16 **  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17 ******************************************************************************/
18
19 #include <iostream>
20 #include <exception>
21 #include <stdexcept>
22 #include <stdarg.h>
23 #include <ctype.h>
24 #include <string>
25 #include "ct.h"
26
27 #ifdef HAVE_WXWINDOWS
28 #include "../src/ctsim.h"
29 #include <wx/log.h>
30 #endif
31
32 /* NAME
33 *   sys_error                   System error handler
34 *
35 * SYNOPSIS
36 *   sys_error (severity, msg, args . . .)
37 *   int severity                Severity of error
38 *   char *msg                   Error message
39 *   args                        Argument list, direct transfer to printf stack
40 */
41
42 static int s_reportErrorLevel = ERR_TRACE;      // Set error reporting level
43
44
45 void sys_error (int severity, const char *msg, ...)
46 {
47   va_list arg;
48
49   va_start(arg, msg);
50
51   std::string strOutput;
52   sys_verror (strOutput, severity, msg, arg);
53
54 #ifdef HAVE_WXWINDOWS
55   if (g_bRunningWXWindows) {
56     if (theApp) {
57       wxCommandEvent eventLog (wxEVT_COMMAND_MENU_SELECTED, MAINMENU_LOG_EVENT );
58       wxString msg (wxConvCurrent->cMB2WX(strOutput.c_str()));
59       if (msg.length() > 0) {
60         msg += wxChar('\n');
61         eventLog.SetString( msg );
62         wxPostEvent( theApp->getMainFrame(), eventLog ); // send log event, thread safe
63       }
64     } else {
65       wxMutexGuiEnter();
66       wxLog::OnLog (wxLOG_Message, wxConvCurrent->cMB2WX(strOutput.c_str()), time(NULL));
67       wxMutexGuiLeave();
68     }
69   }
70   else
71     std::cout << strOutput << "\n";
72 #else
73     std::cout << strOutput << "\n";
74 #endif
75
76   va_end(arg);
77 }
78
79 static unsigned long s_nErrorCount = 0;
80 unsigned long int g_lSysErrorMaxCount = 2000;
81
82
83 void sys_verror (std::string& strOutput, int severity, const char *msg, va_list arg)
84 {
85   if (severity < s_reportErrorLevel)
86     return;     // ignore error if less than reporting level
87
88   std::ostringstream os;
89
90   if (severity > ERR_TRACE)
91     s_nErrorCount++;
92
93   if (severity != ERR_FATAL) {
94     if (s_nErrorCount > g_lSysErrorMaxCount)
95       return;
96     else if (s_nErrorCount == g_lSysErrorMaxCount) {
97       os << "*****************************************************************\n";
98       os << "***   M A X I M U M   E R R O R   C O U N T   R E A C H E D   ***\n";
99       os << "***                                                           ***\n";
100       os << "***           No further errors will be reported              ***\n";
101       os << "*****************************************************************\n";
102       strOutput = os.str();
103       return;
104     }
105   }
106
107   switch (severity) {
108   case ERR_FATAL:
109     os << "FATAL ERROR: ";
110     break;
111   case ERR_SEVERE:
112     os << "SEVERE ERROR: ";
113     break;
114   case ERR_WARNING:
115     os << "WARNING ERROR: ";
116     break;
117   case ERR_TRACE:
118     os << "Trace: ";
119     break;
120   default:
121     os << "Illegal error severity #" << severity << ": ";
122   }
123
124   char errStr[2000];
125
126 #if HAVE_VSNPRINTF
127   vsnprintf (errStr, sizeof(errStr), msg, arg);
128 #elif HAVE_VSPRINTF
129   vsprintf (errStr, msg, arg);
130 #else
131   strncpy (errStr, sizeof(errStr), "Error message not available on this platform.");
132 #endif
133
134   os << errStr;
135   strOutput = os.str();
136
137   if (severity == ERR_FATAL) {
138     std::cerr << strOutput << "\n";
139     throw std::runtime_error (strOutput);
140   }
141
142 #if INTERACTIVE_ERROR_DISPLAY
143   std::cout << "A - Abort  C - Continue  W - Turn off warnings? ";
144   //  fflush(stderr);
145   do
146   {
147     int c = cio_kb_waitc("AaBbCcWw", TRUE);       /* get code from keyboard */
148     c = tolower (c);
149     fputc (c, stderr);
150     fputc (NEWLINE, stderr);
151
152     if (c == 'a')
153       exit (1);
154     else if (c == 'c')
155       return;
156     else if (c == 'w')
157     {
158       sys_error_level (ERR_SEVERE);     /* report severe & fatal errors */
159       break;
160     }
161   } while (TRUE);
162 #endif
163 }
164
165
166 /* NAME
167 *   sys_error_level                     Set error reporting level
168 *
169 * SYNOPSIS
170 *   sys_error_level (severity)
171 *   int severity                Report all error as serious as severity and beyond
172 *
173 * DESCRIPTION
174 *   Causes the system to ignore all error below the level of severity
175 *   For example, if severity == ERR_SEVERE, then report severe & fatal
176 *   error and ignore warnings
177 */
178
179 void
180 sys_error_level (int severity)
181 {
182   if (severity == ERR_FATAL ||
183     severity == ERR_SEVERE ||
184     severity == ERR_WARNING ||
185     severity == ERR_TRACE)
186     s_reportErrorLevel = severity;
187   else
188     s_reportErrorLevel = ERR_WARNING;
189 }
190