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
00038 #include <cpl.h>
00039 #include <cxutils.h>
00040 #include <stdarg.h>
00041 #include <string.h>
00042
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057 #ifndef IRPLIB_ERROR_MAX_STRING_LENGTH
00058 #define IRPLIB_ERROR_MAX_STRING_LENGTH 256
00059 #endif
00060 #ifndef IRPLIB_ERROR_MAX_ERRORS
00061 #define IRPLIB_ERROR_MAX_ERRORS 20
00062 #endif
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074 typedef struct {
00075 char filename [IRPLIB_ERROR_MAX_STRING_LENGTH];
00076 char function [IRPLIB_ERROR_MAX_STRING_LENGTH];
00077 unsigned int linenumber ;
00078 cpl_error_code errorcode ;
00079 char errormessage[IRPLIB_ERROR_MAX_STRING_LENGTH];
00080 char cplmessage [IRPLIB_ERROR_MAX_STRING_LENGTH];
00081 } irplib_error;
00082
00083
00084
00085
00086
00087
00088
00089 static struct {
00090 irplib_error errors[IRPLIB_ERROR_MAX_ERRORS];
00091 cpl_boolean is_empty;
00092 unsigned int first;
00093 unsigned int last;
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108 } queue;
00109
00110
00111
00112
00113 static char error_msg[IRPLIB_ERROR_MAX_STRING_LENGTH];
00114
00115
00116
00117
00118
00119
00120 static cpl_boolean is_initialized = CPL_FALSE;
00121
00122
00123
00124
00127
00143
00144 static void
00145 irplib_error_validate_state(const char *func, const char *file, unsigned int line)
00146 {
00147 if (!is_initialized)
00148 {
00149 cpl_msg_error(cpl_func, "Error handling system was not initialized "
00150 "when called from %s:%s:%d!", file, func, line);
00151 return;
00152 }
00153
00154 if (cpl_error_get_code() == CPL_ERROR_NONE)
00155 {
00156 if (queue.is_empty)
00157 {
00158
00159 }
00160 else
00161 {
00162
00163
00164
00165 irplib_error_reset();
00166 }
00167 }
00168 else
00169 {
00170
00171
00172
00173
00174
00175 irplib_error er;
00176
00177 if (!queue.is_empty)
00178 {
00179 er = queue.errors[queue.last];
00180 }
00181
00182
00183 if (queue.is_empty ||
00184 !(
00185 strcmp(er.filename ,cpl_error_get_file()) == 0 &&
00186 strcmp(er.function ,cpl_error_get_function()) == 0 &&
00187 strcmp(er.cplmessage,cpl_error_get_message()) == 0 &&
00188
00189 er.errorcode == cpl_error_get_code() &&
00190 er.linenumber== cpl_error_get_line()
00191 )
00192 )
00193 {
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205 char file_cpl[IRPLIB_ERROR_MAX_STRING_LENGTH];
00206 char func_cpl[IRPLIB_ERROR_MAX_STRING_LENGTH];
00207 cpl_error_code ec_cpl;
00208 unsigned int line_cpl;
00209
00210 char message_local[IRPLIB_ERROR_MAX_STRING_LENGTH];
00211
00212
00213 strncpy(file_cpl, cpl_error_get_file(),
00214 IRPLIB_ERROR_MAX_STRING_LENGTH - 1);
00215 file_cpl[IRPLIB_ERROR_MAX_STRING_LENGTH-1] = '\0';
00216
00217 strncpy(func_cpl, cpl_error_get_function(),
00218 IRPLIB_ERROR_MAX_STRING_LENGTH - 1);
00219 func_cpl[IRPLIB_ERROR_MAX_STRING_LENGTH-1] = '\0';
00220
00221 ec_cpl = cpl_error_get_code();
00222 line_cpl = cpl_error_get_line();
00223
00224
00225 if (queue.is_empty)
00226 {
00227 cpl_error_reset();
00228 }
00229 else
00230 {
00231 cpl_error_set_macro(er.function,
00232 er.errorcode,
00233 er.filename,
00234 er.linenumber);
00235 }
00236
00237
00238 strncpy(message_local, error_msg,
00239 IRPLIB_ERROR_MAX_STRING_LENGTH-1);
00240 message_local[IRPLIB_ERROR_MAX_STRING_LENGTH-1] = '\0';
00241
00242
00243 irplib_error_set_msg(" ");
00244 irplib_error_push_macro(func_cpl,
00245 ec_cpl,
00246 file_cpl,
00247 line_cpl);
00248 irplib_error_set_msg("%s", message_local);
00249
00250 }
00251
00252 }
00253
00254 return;
00255 }
00256
00257
00277
00278
00279 void irplib_error_push_macro(const char *func,
00280 cpl_error_code ec,
00281 const char *file,
00282 unsigned int line)
00283 {
00284 irplib_error_validate_state(func, file, line);
00285
00286 if (ec == CPL_ERROR_NONE)
00287 {
00288 cpl_msg_error(cpl_func, "The error code CPL_ERROR_NONE was set from "
00289 "%s:%s:%d! Code changed to CPL_ERROR_UNSPECIFIED",
00290 file, func, line);
00291
00292 ec = CPL_ERROR_UNSPECIFIED;
00293 }
00294
00295
00296 if (queue.is_empty)
00297 {
00298
00299 queue.first = 0;
00300 queue.last = 0;
00301 }
00302 else
00303 {
00304
00305 if ((queue.last + 1) % IRPLIB_ERROR_MAX_ERRORS
00306 == (queue.first % IRPLIB_ERROR_MAX_ERRORS))
00307 {
00308
00309 queue.first = (queue.first + 1) % IRPLIB_ERROR_MAX_ERRORS;
00310 }
00311 queue.last = (queue.last + 1) % IRPLIB_ERROR_MAX_ERRORS;
00312 }
00313 queue.is_empty = CPL_FALSE;
00314
00315 cpl_error_set_macro(func, ec, file, line);
00316
00317
00318
00319
00320
00321
00322 strncpy(queue.errors[queue.last].filename , file,
00323 IRPLIB_ERROR_MAX_STRING_LENGTH - 1);
00324 strncpy(queue.errors[queue.last].function , func,
00325 IRPLIB_ERROR_MAX_STRING_LENGTH - 1);
00326 strncpy(queue.errors[queue.last].cplmessage , cpl_error_get_message(),
00327 IRPLIB_ERROR_MAX_STRING_LENGTH - 1);
00328 strncpy(queue.errors[queue.last].errormessage, error_msg,
00329 IRPLIB_ERROR_MAX_STRING_LENGTH - 1);
00330 queue.errors[queue.last].filename [IRPLIB_ERROR_MAX_STRING_LENGTH - 1]
00331 = '\0';
00332 queue.errors[queue.last].function [IRPLIB_ERROR_MAX_STRING_LENGTH - 1]
00333 = '\0';
00334 queue.errors[queue.last].cplmessage [IRPLIB_ERROR_MAX_STRING_LENGTH - 1]
00335 = '\0';
00336 queue.errors[queue.last].errormessage[IRPLIB_ERROR_MAX_STRING_LENGTH - 1]
00337 = '\0';
00338
00339 queue.errors[queue.last].linenumber = line;
00340 queue.errors[queue.last].errorcode = ec;
00341
00342 return;
00343 }
00344
00345
00356
00357 void irplib_error_set_msg(const char *format, ...)
00358 {
00359 va_list al;
00360
00361 va_start(al, format);
00362
00363
00364
00365 cx_vsnprintf(error_msg, IRPLIB_ERROR_MAX_STRING_LENGTH, format, al);
00366 va_end(al);
00367 }
00368
00369
00377
00378 void irplib_error_reset(void)
00379 {
00380 cpl_error_reset();
00381 queue.is_empty = CPL_TRUE;
00382 error_msg[0] = '\0';
00383
00384 is_initialized = CPL_TRUE;
00385 }
00386
00387
00404
00405 void irplib_error_dump_macro(const char *func,
00406 const char *file,
00407 unsigned int line,
00408 cpl_msg_severity severity,
00409 cpl_msg_severity trace_severity)
00410 {
00411
00412
00413
00414 void (*error_msg_func)(const char *, const char *, ...)
00415 #if defined __GNUC__ && __GNUC__ >= 3
00416 __attribute__((format (printf, 2, 3)))
00417 #endif
00418 ;
00419
00420 void (*trace_msg_func)(const char *, const char *, ...)
00421 #if defined __GNUC__ && __GNUC__ >= 3
00422 __attribute__((format (printf, 2, 3)))
00423 #endif
00424 ;
00425
00426 irplib_error_validate_state(func, file, line);
00427
00428 switch (severity)
00429 {
00430 case CPL_MSG_DEBUG:
00431 error_msg_func = &cpl_msg_debug;
00432 break;
00433 case CPL_MSG_INFO:
00434 error_msg_func = &cpl_msg_info;
00435 break;
00436 case CPL_MSG_WARNING:
00437 error_msg_func = &cpl_msg_warning;
00438 break;
00439 case CPL_MSG_ERROR:
00440 error_msg_func = &cpl_msg_error;
00441 break;
00442 case CPL_MSG_OFF:
00443 error_msg_func = NULL;
00444 break;
00445 default:
00446 cpl_msg_error(func, "Unknown message level: %d !",
00447 severity);
00448 error_msg_func = &cpl_msg_error;
00449 break;
00450 }
00451
00452 switch (trace_severity)
00453 {
00454 case CPL_MSG_DEBUG:
00455 trace_msg_func = &cpl_msg_debug;
00456 break;
00457 case CPL_MSG_INFO:
00458 trace_msg_func = &cpl_msg_info;
00459 break;
00460 case CPL_MSG_WARNING:
00461 trace_msg_func = &cpl_msg_warning;
00462 break;
00463 case CPL_MSG_ERROR:
00464 trace_msg_func = &cpl_msg_error;
00465 break;
00466 case CPL_MSG_OFF:
00467 trace_msg_func = NULL;
00468 break;
00469 default:
00470 cpl_msg_error(func, "Unknown message level: %d !",
00471 severity);
00472 trace_msg_func = &cpl_msg_error;
00473 break;
00474 }
00475
00476 if (cpl_error_get_code() == CPL_ERROR_NONE)
00477 {
00478 if (error_msg_func != NULL)
00479 {
00480 error_msg_func(func, "No error has occurred");
00481 }
00482 }
00483 else
00484 {
00485 int i;
00486 cpl_error_code current_ec;
00487
00488
00489
00490
00491
00492
00493
00494
00495 if (trace_msg_func != NULL)
00496 {
00497 trace_msg_func(func, "An error occurred, "
00498 "dumping error trace:");
00499 trace_msg_func(func, " ");
00500 }
00501
00502
00503
00504
00505
00506 current_ec = CPL_ERROR_NONE;
00507 i = queue.first - 1;
00508 do {
00509 const char *c;
00510 cpl_boolean empty_message;
00511
00512 i = (i+1) % IRPLIB_ERROR_MAX_ERRORS;
00513
00514 c = queue.errors[i].errormessage;
00515 empty_message = CPL_TRUE;
00516 while (*c != '\0')
00517 {
00518 empty_message = empty_message && (*c == ' ');
00519 c++;
00520 }
00521
00522
00523
00524
00525
00526 if (empty_message)
00527 {
00528
00529
00530 if (error_msg_func != NULL)
00531 {
00532 error_msg_func(func, "%s",
00533 queue.errors[i].cplmessage);
00534 }
00535 }
00536 else if (queue.errors[i].errorcode == current_ec)
00537 {
00538
00539 if (error_msg_func != NULL)
00540 {
00541 error_msg_func(func, "%s",
00542 queue.errors[i].errormessage);
00543 }
00544 }
00545 else
00546 {
00547
00548
00549 if (error_msg_func != NULL)
00550 {
00551 error_msg_func(func, "%s (%s)",
00552 queue.errors[i].errormessage,
00553 queue.errors[i].cplmessage);
00554 }
00555 }
00556
00557 if (trace_msg_func != NULL)
00558 {
00559 trace_msg_func(func,
00560 " in [%d]%s() at %s:%-3d",
00561
00562
00563 ((queue.last - i
00564 + IRPLIB_ERROR_MAX_ERRORS) %
00565 IRPLIB_ERROR_MAX_ERRORS) + 1,
00566 queue.errors[i].function,
00567 queue.errors[i].filename,
00568 queue.errors[i].linenumber);
00569 trace_msg_func(func, " ");
00570 }
00571
00572 current_ec = queue.errors[i].errorcode;
00573
00574 } while ((unsigned int) i != queue.last);
00575
00576 }
00577 }
00578