00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #ifdef HAVE_CONFIG_H
00022 #include "config.h"
00023 #endif
00024
00025 #include <stdlib.h>
00026 #include <string.h>
00027 #include <assert.h>
00028
00029 #include "libdefs.h"
00030 #include "vacopy.h"
00031 #include "error.h"
00032
00033 #define STEP_ERROR_INDEX(I)\
00034 if(++(I) >= fid_ERROR_MAX)\
00035 {\
00036 (I)=0;\
00037 }
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047 void fid_error_init(fid_Error *error, fid_Errormode mode)
00048 {
00049 int i;
00050
00051 if(error == NULL)
00052 {
00053 return;
00054 }
00055
00056 assert(mode == fid_ERRORMODE_FIFO || mode == fid_ERRORMODE_DEEPEST || mode == fid_ERRORMODE_KEEP_LAST);
00057
00058 error->num_of_errors=error->first_error=0;
00059 error->mode=mode;
00060 error->overflow=error->outofmem=0;
00061 for(i=0;i < fid_ERROR_MAX; ++i)
00062 {
00063 error->errors[i]=NULL;
00064 }
00065 }
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078 void fid_error_init_default(fid_Error *error)
00079 {
00080 fid_error_init(error,fid_ERRORMODE_FIFO);
00081 }
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095 void fid_error_free(fid_Error *error)
00096 {
00097 int i, err;
00098
00099 if(error == NULL)
00100 {
00101 return;
00102 }
00103
00104 err=error->first_error;
00105 for(i=0; i < error->num_of_errors; ++i)
00106 {
00107 assert(error->errors[err] != NULL);
00108 free(error->errors[err]);
00109 error->errors[err]=NULL;
00110 STEP_ERROR_INDEX(err);
00111 }
00112 error->num_of_errors=error->first_error=0;
00113 error->overflow=error->outofmem=0;
00114 }
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131 static char *make_message(const char *fmt, va_list ap, fid_Error *error)
00132 {
00133 #ifdef ENABLE_VSNPRINTF_WORKAROUND
00134 char dummy;
00135 #endif
00136 va_list copy;
00137 int bufsize;
00138 char *buffer=NULL;
00139
00140 #ifndef S_SPLINT_S
00141 va_copy(copy,ap);
00142 #endif
00143 bufsize=vsnprintf(
00144 #ifdef ENABLE_VSNPRINTF_WORKAROUND
00145 &dummy,1,
00146 #else
00147 NULL,0,
00148 #endif
00149 fmt,copy)+1;
00150 va_end(copy);
00151 if(bufsize > 1)
00152 {
00153 if((buffer=(char *)malloc(sizeof(char)*bufsize)) != NULL)
00154 {
00155 #ifndef S_SPLINT_S
00156 va_copy(copy,ap);
00157 #endif
00158 (void)vsnprintf(buffer,(size_t)bufsize,fmt,copy);
00159 va_end(copy);
00160 }
00161 else
00162 {
00163 error->outofmem=1;
00164 }
00165 }
00166 return buffer;
00167 }
00168
00169
00170
00171
00172
00173
00174
00175
00176 static void append_message(fid_Error *error, char *buffer)
00177 {
00178 if(buffer != NULL)
00179 {
00180 #ifdef DEBUG
00181 char *bufptr, c;
00182
00183 fprintf(stderr,"THROW ERROR: \"%s\"\n",buffer);
00184
00185 for(bufptr=buffer; (c=*bufptr) != '\0'; ++bufptr)
00186 {
00187 if(c == '\n')
00188 {
00189 fprintf(stderr,"%s(): WARNING: error message contains newlines.\n",
00190 __func__);
00191 fprintf(stderr,"%s(): WARNING: ---> %s <---\n",__func__,buffer);
00192 break;
00193 }
00194 }
00195 #endif
00196
00197
00198 if(error->num_of_errors < fid_ERROR_MAX)
00199 {
00200
00201 error->errors[error->num_of_errors++]=buffer;
00202 }
00203 else
00204 {
00205
00206 error->overflow=1;
00207 switch(error->mode)
00208 {
00209 case fid_ERRORMODE_FIFO:
00210 assert(error->errors[error->first_error] != NULL);
00211 free(error->errors[error->first_error]);
00212 error->errors[error->first_error]=buffer;
00213 STEP_ERROR_INDEX(error->first_error);
00214 break;
00215 case fid_ERRORMODE_KEEP_LAST:
00216 assert(error->errors[fid_ERROR_MAX-1] != NULL);
00217 free(error->errors[fid_ERROR_MAX-1]);
00218 error->errors[fid_ERROR_MAX-1]=buffer;
00219 break;
00220 default:
00221 abort();
00222 }
00223 }
00224 }
00225 #ifdef DEBUG
00226 else if(error->outofmem)
00227 {
00228 fprintf(stderr,"THROW ERROR, OUT OF MEMORY (%s)\n",buffer);
00229 }
00230 else
00231 {
00232 fprintf(stderr,"THROW ERROR, EMPTY MESSAGE (%s)\n",buffer);
00233 }
00234 #endif
00235 }
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249 void fid_error_throw(fid_Error *error, const char *fmt, ...)
00250 {
00251 char *buffer;
00252 va_list ap;
00253
00254 if(error == NULL || fmt == NULL)
00255 {
00256
00257 return;
00258 }
00259 else if(error->num_of_errors == fid_ERROR_MAX &&
00260 error->mode == fid_ERRORMODE_DEEPEST)
00261 {
00262
00263 #ifdef DEBUG
00264 fprintf(stderr,"THROW ERROR, OVERFLOW (%s)\n",fmt);
00265 #endif
00266 error->overflow=1;
00267 return;
00268 }
00269
00270 va_start(ap,fmt);
00271 buffer=make_message(fmt,ap,error);
00272 va_end(ap);
00273
00274 assert(buffer != NULL || error->outofmem == 1 || strlen(fmt) == 0);
00275
00276 append_message(error,buffer);
00277 }
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301 void fid_error_throw_errno(fid_Error *error, int errnum, const char *fmt, ...)
00302 {
00303 char *buffer=NULL, *str;
00304 va_list ap;
00305
00306 if(error == NULL || errnum == 0)
00307 {
00308
00309 return;
00310 }
00311
00312 str=strerror(errnum);
00313
00314 if(fmt != NULL)
00315 {
00316 va_start(ap,fmt);
00317 buffer=make_message(fmt,ap,error);
00318 va_end(ap);
00319 }
00320 else if(str != NULL)
00321 {
00322
00323 append_message(error,str);
00324 }
00325 else
00326 {
00327
00328 fid_error_throw(error,"unknown error %d",errnum);
00329 }
00330
00331 if(buffer != NULL)
00332 {
00333
00334 if(str != NULL)
00335 {
00336
00337 fid_error_throw(error,"%s: %s",buffer,str);
00338 }
00339 else
00340 {
00341
00342 fid_error_throw(error,"%s: unknown error %d",buffer,errnum);
00343 }
00344 free(buffer);
00345 }
00346 else
00347 {
00348
00349
00350 append_message(error,NULL);
00351 }
00352 }
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372 int fid_error_dump(const fid_Error *error, FILE *stream)
00373 {
00374 int i, err, last;
00375 int retval;
00376
00377 if(error == NULL)
00378 {
00379 return 0;
00380 }
00381 else if(!(retval=fid_ERROR_OCCURRED(error)) || stream == NULL)
00382 {
00383 return retval;
00384 }
00385
00386 if(error->num_of_errors == (int)1)
00387 {
00388 assert(error->first_error == 0);
00389 assert(error->errors[0] != NULL);
00390 fprintf(stream,"Error: %s\n",error->errors[0]);
00391 }
00392 else
00393 {
00394 assert(error->first_error < fid_ERROR_MAX);
00395 fprintf(stream,"-----\nErrors:\n");
00396 if(error->overflow && error->mode == fid_ERRORMODE_KEEP_LAST)
00397 {
00398 last=error->num_of_errors-1;
00399 }
00400 else
00401 {
00402 last=error->num_of_errors;
00403 }
00404
00405 if(error->overflow && error->mode == fid_ERRORMODE_FIFO)
00406 {
00407 fprintf(stream,"??: ...\n");
00408 }
00409
00410 err=error->first_error;
00411 for(i=0; i < last; ++i)
00412 {
00413 assert(err < fid_ERROR_MAX);
00414 assert(error->errors[err] != NULL);
00415 fprintf(stream,"%2d: %s\n",i+1,error->errors[err]);
00416 STEP_ERROR_INDEX(err);
00417 }
00418
00419 if(error->overflow)
00420 {
00421 switch(error->mode)
00422 {
00423 case fid_ERRORMODE_KEEP_LAST:
00424 fprintf(stream," ...\n");
00425 assert(error->errors[fid_ERROR_MAX-1] != NULL);
00426 fprintf(stream,"%02u: %s\n",(unsigned int)fid_ERROR_MAX,
00427 error->errors[fid_ERROR_MAX-1]);
00428 break;
00429 case fid_ERRORMODE_DEEPEST:
00430 fprintf(stream," ...\n");
00431 break;
00432 default:
00433 break;
00434 }
00435 }
00436
00437 if(error->outofmem)
00438 {
00439 fprintf(stream,"xx: at least one error message got lost due to "
00440 "out-of-memory condition.\n");
00441 }
00442 fprintf(stream,"-----\n");
00443 }
00444
00445 return retval;
00446 }
00447
00448