00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #ifdef HAVE_CONFIG_H
00029 #include <config.h>
00030 #endif
00031
00032
00033
00034
00035
00036 #include "irplib_error.h"
00037 #include <string.h>
00038 #include <cpl.h>
00039 #include <cxutils.h>
00040 #include <stdarg.h>
00041
00046
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058 #define MAX_STRING_LENGTH 200
00059 #define MAX_ERRORS 20
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069 typedef struct
00070 {
00071 char filename[MAX_STRING_LENGTH];
00072 char function[MAX_STRING_LENGTH];
00073 unsigned int linenumber;
00074 cpl_error_code errorcode;
00075 char errormessage[MAX_STRING_LENGTH];
00076 char cplmessage[MAX_STRING_LENGTH];
00077 } irplib_error;
00078
00079
00080
00081
00082
00083
00084 static struct
00085 {
00086 irplib_error errors[MAX_ERRORS];
00087 cpl_boolean is_empty;
00088 unsigned int first;
00089 unsigned int last;
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104 } queue;
00105
00106
00107
00108 static char error_msg[MAX_STRING_LENGTH];
00109
00110
00111
00112
00113
00114
00115 static cpl_boolean is_initialized = CPL_FALSE;
00116
00117
00118
00119
00120
00121
00137
00138 static void
00139 irplib_error_validate_state (const char *func, const char *file,
00140 unsigned int line)
00141 {
00142 if (!is_initialized) {
00143 cpl_msg_error (__func__, "Error handling system was not initialized "
00144 "when called from %s:%s:%d!", file, func, line);
00145 return;
00146 }
00147 if (cpl_error_get_code () == CPL_ERROR_NONE) {
00148 if (queue.is_empty) {
00149
00150 }
00151 else {
00152
00153
00154
00155 xsh_irplib_error_reset ();
00156 }
00157 }
00158 else {
00159
00160
00161
00162
00163
00164 irplib_error er;
00165
00166
00167 if (!queue.is_empty) {
00168 er = queue.errors[queue.last];
00169 }
00170
00171
00172 if (queue.is_empty ||
00173 !(strcmp (er.filename, cpl_error_get_file ()) == 0 &&
00174 strcmp (er.function, cpl_error_get_function ()) == 0 &&
00175 strcmp (er.cplmessage, cpl_error_get_message ()) == 0 &&
00176
00177 er.errorcode == cpl_error_get_code () &&
00178 er.linenumber == cpl_error_get_line ()
00179 )
00180 ) {
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192 char file_cpl[MAX_STRING_LENGTH];
00193 char func_cpl[MAX_STRING_LENGTH];
00194 cpl_error_code ec_cpl;
00195 unsigned int line_cpl;
00196
00197 char message_local[MAX_STRING_LENGTH];
00198
00199
00200
00201 strncpy (file_cpl, cpl_error_get_file (), MAX_STRING_LENGTH - 1);
00202 file_cpl[MAX_STRING_LENGTH - 1] = '\0';
00203
00204 strncpy (func_cpl, cpl_error_get_function (), MAX_STRING_LENGTH - 1);
00205 func_cpl[MAX_STRING_LENGTH - 1] = '\0';
00206
00207 ec_cpl = cpl_error_get_code ();
00208 line_cpl = cpl_error_get_line ();
00209
00210
00211 if (queue.is_empty) {
00212 cpl_error_reset ();
00213 }
00214 else {
00215 cpl_error_set_message_macro (er.function,
00216 er.errorcode, er.filename, er.linenumber," ");
00217 }
00218
00219
00220 strncpy (message_local, error_msg, MAX_STRING_LENGTH - 1);
00221 message_local[MAX_STRING_LENGTH - 1] = '\0';
00222
00223
00224 xsh_irplib_error_set_msg (" ");
00225 xsh_irplib_error_push_macro (func_cpl, ec_cpl, file_cpl, line_cpl);
00226 xsh_irplib_error_set_msg ("%s", message_local);
00227
00228 }
00229
00230 }
00231
00232 return;
00233 }
00234
00235
00256
00257
00258 cpl_error_code
00259 xsh_irplib_error_push_macro (const char *func,
00260 cpl_error_code ec,
00261 const char *file, unsigned int line)
00262 {
00263 irplib_error_validate_state (func, file, line);
00264
00265 if (ec == CPL_ERROR_NONE) {
00266 cpl_msg_error (__func__, "The error code CPL_ERROR_NONE was set from "
00267 "%s:%s:%d! Code changed to CPL_ERROR_UNSPECIFIED",
00268 file, func, line);
00269
00270 ec = CPL_ERROR_UNSPECIFIED;
00271 }
00272
00273
00274 if (queue.is_empty) {
00275
00276 queue.first = 0;
00277 queue.last = 0;
00278 }
00279 else {
00280
00281 if ((queue.last + 1) % MAX_ERRORS == (queue.first % MAX_ERRORS)) {
00282
00283 queue.first = (queue.first + 1) % MAX_ERRORS;
00284 }
00285 queue.last = (queue.last + 1) % MAX_ERRORS;
00286 }
00287 queue.is_empty = CPL_FALSE;
00288 cpl_error_set_message_macro (func, ec, file, line," ");
00289
00290
00291
00292
00293
00294
00295 strncpy (queue.errors[queue.last].filename, file, MAX_STRING_LENGTH - 1);
00296 strncpy (queue.errors[queue.last].function, func, MAX_STRING_LENGTH - 1);
00297 strncpy (queue.errors[queue.last].cplmessage, cpl_error_get_message (),
00298 MAX_STRING_LENGTH - 1);
00299 strncpy (queue.errors[queue.last].errormessage, error_msg,
00300 MAX_STRING_LENGTH - 1);
00301 queue.errors[queue.last].filename[MAX_STRING_LENGTH - 1] = '\0';
00302 queue.errors[queue.last].function[MAX_STRING_LENGTH - 1] = '\0';
00303 queue.errors[queue.last].cplmessage[MAX_STRING_LENGTH - 1] = '\0';
00304 queue.errors[queue.last].errormessage[MAX_STRING_LENGTH - 1] = '\0';
00305
00306 queue.errors[queue.last].linenumber = line;
00307 queue.errors[queue.last].errorcode = ec;
00308
00309 return ec;
00310 }
00311
00312
00323
00324 void
00325 xsh_irplib_error_set_msg (const char *format, ...)
00326 {
00327 va_list al;
00328
00329 va_start (al, format);
00330
00331
00332
00333 cx_vsnprintf (error_msg, MAX_STRING_LENGTH, format, al);
00334 va_end (al);
00335 }
00336
00337
00345
00346 void
00347 xsh_irplib_error_reset ( void )
00348 {
00349 cpl_error_reset ();
00350 queue.is_empty = CPL_TRUE;
00351 error_msg[0] = '\0';
00352
00353 is_initialized = CPL_TRUE;
00354 }
00355
00356
00373
00374 void
00375 xsh_irplib_error_dump_macro (const char *func,
00376 const char *file,
00377 unsigned int line,
00378 cpl_msg_severity severity,
00379 cpl_msg_severity trace_severity)
00380 {
00381
00382
00383
00384 void (*error_msg_func) (const char *, const char *, ...);
00385 void (*trace_msg_func) (const char *, const char *, ...);
00386
00387 irplib_error_validate_state (func, file, line);
00388
00389 switch (severity) {
00390 case CPL_MSG_DEBUG:
00391 error_msg_func = (void(*)(const char*,const char*,...))&cpl_msg_debug;
00392 break;
00393 case CPL_MSG_INFO:
00394 error_msg_func = (void(*)(const char*,const char*,...))&cpl_msg_info;
00395 break;
00396 case CPL_MSG_WARNING:
00397 error_msg_func = (void(*)(const char*,const char*,...))&cpl_msg_warning;
00398 break;
00399 case CPL_MSG_ERROR:
00400 error_msg_func = (void(*)(const char*,const char*,...))&cpl_msg_error;
00401 break;
00402 case CPL_MSG_OFF:
00403 error_msg_func = NULL;
00404 break;
00405 default:
00406 cpl_msg_error (func, "Unknown message level: %d !", severity);
00407 error_msg_func = (void(*)(const char*,const char*,...))&cpl_msg_error;
00408 break;
00409 }
00410
00411 switch (trace_severity) {
00412 case CPL_MSG_DEBUG:
00413 trace_msg_func = (void(*)(const char*,const char*,...))&cpl_msg_debug;
00414 break;
00415 case CPL_MSG_INFO:
00416 trace_msg_func = (void(*)(const char*,const char*,...))&cpl_msg_info;
00417 break;
00418 case CPL_MSG_WARNING:
00419 trace_msg_func = (void(*)(const char*,const char*,...))&cpl_msg_warning;
00420 break;
00421 case CPL_MSG_ERROR:
00422 trace_msg_func = (void(*)(const char*,const char*,...))&cpl_msg_error;
00423 break;
00424 case CPL_MSG_OFF:
00425 trace_msg_func = NULL;
00426 break;
00427 default:
00428 cpl_msg_error (func, "Unknown message level: %d !", severity);
00429 trace_msg_func = (void(*)(const char*,const char*,...))&cpl_msg_error;
00430 break;
00431 }
00432
00433 if (cpl_error_get_code () == CPL_ERROR_NONE) {
00434 if (error_msg_func != NULL) {
00435 error_msg_func (func, "No error has occurred");
00436 }
00437 }
00438 else {
00439 int i;
00440 cpl_error_code current_ec;
00441
00442
00443
00444
00445
00446
00447
00448
00449 if (trace_msg_func != NULL) {
00450 trace_msg_func (func, "An error occurred, " "dumping error trace:");
00451 trace_msg_func (func, " ");
00452 }
00453
00454
00455
00456
00457
00458 current_ec = CPL_ERROR_NONE;
00459 i = queue.first - 1;
00460 do {
00461 const char *c;
00462 cpl_boolean empty_message;
00463
00464 i = (i + 1) % MAX_ERRORS;
00465
00466 c = queue.errors[i].errormessage;
00467 empty_message = CPL_TRUE;
00468 while (*c != '\0') {
00469 empty_message = empty_message && (*c == ' ');
00470 c++;
00471 }
00472
00473
00474
00475
00476
00477 if (empty_message) {
00478
00479
00480 if (error_msg_func != NULL) {
00481 error_msg_func (func, "%s", queue.errors[i].cplmessage);
00482 }
00483 }
00484 else if (queue.errors[i].errorcode == current_ec) {
00485
00486 if (error_msg_func != NULL) {
00487 error_msg_func (func, "%s", queue.errors[i].errormessage);
00488 }
00489 }
00490 else {
00491
00492
00493 if (error_msg_func != NULL) {
00494 error_msg_func (func, "%s (%s)",
00495 queue.errors[i].errormessage,
00496 queue.errors[i].cplmessage);
00497 }
00498 }
00499
00500 if (trace_msg_func != NULL) {
00501 trace_msg_func (func, " in [%d]%s() at %s:%-3d",
00502
00503
00504 ((queue.last - i + MAX_ERRORS) %
00505 MAX_ERRORS) + 1,
00506 queue.errors[i].function,
00507 queue.errors[i].filename, queue.errors[i].linenumber);
00508 trace_msg_func (func, " ");
00509 }
00510
00511 current_ec = queue.errors[i].errorcode;
00512
00513 } while ((unsigned int) i != queue.last);
00514
00515 }
00516 }
00517