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