Home | History | Annotate | Download | only in MagickCore
      1 /*
      2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      3 %                                                                             %
      4 %                                                                             %
      5 %                                                                             %
      6 %        EEEEE  X   X   CCCC  EEEEE  PPPP  TTTTT  IIIII   OOO   N   N         %
      7 %        E       X X   C      E      P   P   T      I    O   O  NN  N         %
      8 %        EEE      X    C      EEE    PPPP    T      I    O   O  N N N         %
      9 %        E       X X   C      E      P       T      I    O   O  N  NN         %
     10 %        EEEEE   X  X   CCCC  EEEEE  P       T    IIIII   OOO   N   N         %
     11 %                                                                             %
     12 %                                                                             %
     13 %                        MagickCore Exception Methods                         %
     14 %                                                                             %
     15 %                             Software Design                                 %
     16 %                                  Cristy                                     %
     17 %                                July 1993                                    %
     18 %                                                                             %
     19 %                                                                             %
     20 %  Copyright 1999-2016 ImageMagick Studio LLC, a non-profit organization      %
     21 %  dedicated to making software imaging solutions freely available.           %
     22 %                                                                             %
     23 %  You may not use this file except in compliance with the License.  You may  %
     24 %  obtain a copy of the License at                                            %
     25 %                                                                             %
     26 %    http://www.imagemagick.org/script/license.php                            %
     27 %                                                                             %
     28 %  Unless required by applicable law or agreed to in writing, software        %
     29 %  distributed under the License is distributed on an "AS IS" BASIS,          %
     30 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
     31 %  See the License for the specific language governing permissions and        %
     32 %  limitations under the License.                                             %
     33 %                                                                             %
     34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     35 %
     36 %
     37 %
     38 */
     39 
     40 /*
     42   Include declarations.
     43 */
     44 #include "MagickCore/studio.h"
     45 #include "MagickCore/client.h"
     46 #include "MagickCore/exception.h"
     47 #include "MagickCore/exception-private.h"
     48 #include "MagickCore/linked-list.h"
     49 #include "MagickCore/locale_.h"
     50 #include "MagickCore/log.h"
     51 #include "MagickCore/magick.h"
     52 #include "MagickCore/memory_.h"
     53 #include "MagickCore/string_.h"
     54 #include "MagickCore/utility.h"
     55 #include "MagickCore/utility-private.h"
     56 
     57 /*
     59   Forward declarations.
     60 */
     61 #if defined(__cplusplus) || defined(c_plusplus)
     62 extern "C" {
     63 #endif
     64 
     65 static void
     66   DefaultErrorHandler(const ExceptionType,const char *,const char *),
     67   DefaultFatalErrorHandler(const ExceptionType,const char *,const char *),
     68   DefaultWarningHandler(const ExceptionType,const char *,const char *);
     69 
     70 #if defined(__cplusplus) || defined(c_plusplus)
     71 }
     72 #endif
     73 
     74 /*
     76   Global declarations.
     77 */
     78 #define MaxExceptions  128
     79 
     80 /*
     82   Global declarations.
     83 */
     84 static ErrorHandler
     85   error_handler = DefaultErrorHandler;
     86 
     87 static FatalErrorHandler
     88   fatal_error_handler = DefaultFatalErrorHandler;
     89 
     90 static WarningHandler
     91   warning_handler = DefaultWarningHandler;
     92 
     93 /*
     95 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     96 %                                                                             %
     97 %                                                                             %
     98 %                                                                             %
     99 %   A c q u i r e E x c e p t i o n I n f o                                   %
    100 %                                                                             %
    101 %                                                                             %
    102 %                                                                             %
    103 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    104 %
    105 %  AcquireExceptionInfo() allocates the ExceptionInfo structure.
    106 %
    107 %  The format of the AcquireExceptionInfo method is:
    108 %
    109 %      ExceptionInfo *AcquireExceptionInfo(void)
    110 %
    111 */
    112 MagickExport ExceptionInfo *AcquireExceptionInfo(void)
    113 {
    114   ExceptionInfo
    115     *exception;
    116 
    117   exception=(ExceptionInfo *) AcquireMagickMemory(sizeof(*exception));
    118   if (exception == (ExceptionInfo *) NULL)
    119     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
    120   InitializeExceptionInfo(exception);
    121   exception->relinquish=MagickTrue;
    122   return(exception);
    123 }
    124 
    125 /*l
    127 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    128 %                                                                             %
    129 %                                                                             %
    130 %                                                                             %
    131 %   C l e a r M a g i c k E x c e p t i o n                                   %
    132 %                                                                             %
    133 %                                                                             %
    134 %                                                                             %
    135 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    136 %
    137 %  ClearMagickException() clears any exception that may not have been caught
    138 %  yet.
    139 %
    140 %  The format of the ClearMagickException method is:
    141 %
    142 %      ClearMagickException(ExceptionInfo *exception)
    143 %
    144 %  A description of each parameter follows:
    145 %
    146 %    o exception: the exception info.
    147 %
    148 */
    149 
    150 static void *DestroyExceptionElement(void *exception)
    151 {
    152   register ExceptionInfo
    153     *p;
    154 
    155   p=(ExceptionInfo *) exception;
    156   if (p->reason != (char *) NULL)
    157     p->reason=DestroyString(p->reason);
    158   if (p->description != (char *) NULL)
    159     p->description=DestroyString(p->description);
    160   p=(ExceptionInfo *) RelinquishMagickMemory(p);
    161   return((void *) NULL);
    162 }
    163 
    164 MagickExport void ClearMagickException(ExceptionInfo *exception)
    165 {
    166   assert(exception != (ExceptionInfo *) NULL);
    167   assert(exception->signature == MagickCoreSignature);
    168   if (exception->exceptions == (void *) NULL)
    169     return;
    170   LockSemaphoreInfo(exception->semaphore);
    171   ClearLinkedList((LinkedListInfo *) exception->exceptions,
    172     DestroyExceptionElement);
    173   exception->severity=UndefinedException;
    174   exception->reason=(char *) NULL;
    175   exception->description=(char *) NULL;
    176   UnlockSemaphoreInfo(exception->semaphore);
    177   errno=0;
    178 }
    179 
    180 /*
    182 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    183 %                                                                             %
    184 %                                                                             %
    185 %                                                                             %
    186 %   C a t c h E x c e p t i o n                                               %
    187 %                                                                             %
    188 %                                                                             %
    189 %                                                                             %
    190 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    191 %
    192 %  CatchException() returns if no exceptions is found otherwise it reports
    193 %  the exception as a warning, error, or fatal depending on the severity.
    194 %
    195 %  The format of the CatchException method is:
    196 %
    197 %      CatchException(ExceptionInfo *exception)
    198 %
    199 %  A description of each parameter follows:
    200 %
    201 %    o exception: the exception info.
    202 %
    203 */
    204 MagickExport void CatchException(ExceptionInfo *exception)
    205 {
    206   register const ExceptionInfo
    207     *p;
    208 
    209   ssize_t
    210     i;
    211 
    212   assert(exception != (ExceptionInfo *) NULL);
    213   assert(exception->signature == MagickCoreSignature);
    214   if (exception->exceptions  == (void *) NULL)
    215     return;
    216   LockSemaphoreInfo(exception->semaphore);
    217   ResetLinkedListIterator((LinkedListInfo *) exception->exceptions);
    218   p=(const ExceptionInfo *) GetNextValueInLinkedList((LinkedListInfo *)
    219     exception->exceptions);
    220   for (i=0; p != (const ExceptionInfo *) NULL; i++)
    221   {
    222     if (i < MaxExceptions)
    223       {
    224         if ((p->severity >= WarningException) && (p->severity < ErrorException))
    225           MagickWarning(p->severity,p->reason,p->description);
    226         if ((p->severity >= ErrorException) &&
    227             (p->severity < FatalErrorException))
    228           MagickError(p->severity,p->reason,p->description);
    229       }
    230     else
    231       if (i == MaxExceptions)
    232         MagickError(ResourceLimitError,"too many exceptions",
    233           "exception processing is suspended");
    234     if (p->severity >= FatalErrorException)
    235       MagickFatalError(p->severity,p->reason,p->description);
    236     p=(const ExceptionInfo *) GetNextValueInLinkedList((LinkedListInfo *)
    237       exception->exceptions);
    238   }
    239   UnlockSemaphoreInfo(exception->semaphore);
    240   ClearMagickException(exception);
    241 }
    242 
    243 /*
    245 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    246 %                                                                             %
    247 %                                                                             %
    248 %                                                                             %
    249 %   C l o n e E x c e p t i o n I n f o                                       %
    250 %                                                                             %
    251 %                                                                             %
    252 %                                                                             %
    253 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    254 %
    255 %  CloneExceptionInfo() clones the ExceptionInfo structure.
    256 %
    257 %  The format of the CloneExceptionInfo method is:
    258 %
    259 %      ExceptionInfo *CloneException(ExceptionInfo *exception)
    260 %
    261 %  A description of each parameter follows:
    262 %
    263 %    o exception: the exception info.
    264 %
    265 */
    266 MagickExport ExceptionInfo *CloneExceptionInfo(ExceptionInfo *exception)
    267 {
    268   ExceptionInfo
    269     *clone_exception;
    270 
    271   clone_exception=(ExceptionInfo *) AcquireMagickMemory(sizeof(*exception));
    272   if (clone_exception == (ExceptionInfo *) NULL)
    273     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
    274   InitializeExceptionInfo(clone_exception);
    275   InheritException(clone_exception,exception);
    276   clone_exception->relinquish=MagickTrue;
    277   return(clone_exception);
    278 }
    279 
    280 /*
    282 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    283 %                                                                             %
    284 %                                                                             %
    285 %                                                                             %
    286 +   D e f a u l t E r r o r H a n d l e r                                     %
    287 %                                                                             %
    288 %                                                                             %
    289 %                                                                             %
    290 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    291 %
    292 %  DefaultErrorHandler() displays an error reason.
    293 %
    294 %  The format of the DefaultErrorHandler method is:
    295 %
    296 %      void MagickError(const ExceptionType severity,const char *reason,
    297 %        const char *description)
    298 %
    299 %  A description of each parameter follows:
    300 %
    301 %    o severity: Specifies the numeric error category.
    302 %
    303 %    o reason: Specifies the reason to display before terminating the
    304 %      program.
    305 %
    306 %    o description: Specifies any description to the reason.
    307 %
    308 */
    309 static void DefaultErrorHandler(const ExceptionType magick_unused(severity),
    310   const char *reason,const char *description)
    311 {
    312   magick_unreferenced(severity);
    313 
    314   if (reason == (char *) NULL)
    315     return;
    316   (void) FormatLocaleFile(stderr,"%s: %s",GetClientName(),reason);
    317   if (description != (char *) NULL)
    318     (void) FormatLocaleFile(stderr," (%s)",description);
    319   (void) FormatLocaleFile(stderr,".\n");
    320   (void) fflush(stderr);
    321 }
    322 
    323 /*
    325 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    326 %                                                                             %
    327 %                                                                             %
    328 %                                                                             %
    329 +   D e f a u l t F a t a l E r r o r H a n d l e r                           %
    330 %                                                                             %
    331 %                                                                             %
    332 %                                                                             %
    333 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    334 %
    335 %  DefaultFatalErrorHandler() displays an error reason and then terminates the
    336 %  program.
    337 %
    338 %  The format of the DefaultFatalErrorHandler method is:
    339 %
    340 %      void MagickFatalError(const ExceptionType severity,const char *reason,
    341 %        const char *description)
    342 %
    343 %  A description of each parameter follows:
    344 %
    345 %    o severity: Specifies the numeric error category.
    346 %
    347 %    o reason: Specifies the reason to display before terminating the program.
    348 %
    349 %    o description: Specifies any description to the reason.
    350 %
    351 */
    352 static void DefaultFatalErrorHandler(const ExceptionType severity,
    353   const char *reason,const char *description)
    354 {
    355   if (reason == (char *) NULL)
    356     return;
    357   (void) FormatLocaleFile(stderr,"%s: %s",GetClientName(),reason);
    358   if (description != (char *) NULL)
    359     (void) FormatLocaleFile(stderr," (%s)",description);
    360   (void) FormatLocaleFile(stderr,".\n");
    361   (void) fflush(stderr);
    362   MagickCoreTerminus();
    363   exit((int) (severity-FatalErrorException)+1);
    364 }
    365 
    366 /*
    368 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    369 %                                                                             %
    370 %                                                                             %
    371 %                                                                             %
    372 +   D e f a u l t W a r n i n g H a n d l e r                                 %
    373 %                                                                             %
    374 %                                                                             %
    375 %                                                                             %
    376 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    377 %
    378 %  DefaultWarningHandler() displays a warning reason.
    379 %
    380 %  The format of the DefaultWarningHandler method is:
    381 %
    382 %      void DefaultWarningHandler(const ExceptionType severity,
    383 %        const char *reason,const char *description)
    384 %
    385 %  A description of each parameter follows:
    386 %
    387 %    o severity: Specifies the numeric warning category.
    388 %
    389 %    o reason: Specifies the reason to display before terminating the
    390 %      program.
    391 %
    392 %    o description: Specifies any description to the reason.
    393 %
    394 */
    395 static void DefaultWarningHandler(const ExceptionType magick_unused(severity),
    396   const char *reason,const char *description)
    397 {
    398   magick_unreferenced(severity);
    399 
    400   if (reason == (char *) NULL)
    401     return;
    402   (void) FormatLocaleFile(stderr,"%s: %s",GetClientName(),reason);
    403   if (description != (char *) NULL)
    404     (void) FormatLocaleFile(stderr," (%s)",description);
    405   (void) FormatLocaleFile(stderr,".\n");
    406   (void) fflush(stderr);
    407 }
    408 
    409 /*
    411 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    412 %                                                                             %
    413 %                                                                             %
    414 %                                                                             %
    415 %   D e s t r o y E x c e p t i o n I n f o                                   %
    416 %                                                                             %
    417 %                                                                             %
    418 %                                                                             %
    419 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    420 %
    421 %  DestroyExceptionInfo() deallocates memory associated with an exception.
    422 %
    423 %  The format of the DestroyExceptionInfo method is:
    424 %
    425 %      ExceptionInfo *DestroyExceptionInfo(ExceptionInfo *exception)
    426 %
    427 %  A description of each parameter follows:
    428 %
    429 %    o exception: the exception info.
    430 %
    431 */
    432 MagickExport ExceptionInfo *DestroyExceptionInfo(ExceptionInfo *exception)
    433 {
    434   MagickBooleanType
    435     relinquish;
    436 
    437   assert(exception != (ExceptionInfo *) NULL);
    438   assert(exception->signature == MagickCoreSignature);
    439   if (exception->semaphore == (SemaphoreInfo *) NULL)
    440     ActivateSemaphoreInfo(&exception->semaphore);
    441   LockSemaphoreInfo(exception->semaphore);
    442   exception->severity=UndefinedException;
    443   if (exception->relinquish != MagickFalse)
    444     {
    445       exception->signature=(~MagickCoreSignature);
    446       if (exception->exceptions != (void *) NULL)
    447         exception->exceptions=(void *) DestroyLinkedList((LinkedListInfo *)
    448           exception->exceptions,DestroyExceptionElement);
    449     }
    450   else if (exception->exceptions != (void *) NULL)
    451     ClearLinkedList((LinkedListInfo *) exception->exceptions,
    452       DestroyExceptionElement);
    453   relinquish=exception->relinquish;
    454   UnlockSemaphoreInfo(exception->semaphore);
    455   if (relinquish != MagickFalse)
    456     {
    457       RelinquishSemaphoreInfo(&exception->semaphore);
    458       exception=(ExceptionInfo *) RelinquishMagickMemory(exception);
    459     }
    460   return(exception);
    461 }
    462 
    463 /*
    465 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    466 %                                                                             %
    467 %                                                                             %
    468 %                                                                             %
    469 %   G e t E x c e p t i o n M e s s a g e                                     %
    470 %                                                                             %
    471 %                                                                             %
    472 %                                                                             %
    473 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    474 %
    475 %  GetExceptionMessage() returns the error message defined by the specified
    476 %  error code.
    477 %
    478 %  The format of the GetExceptionMessage method is:
    479 %
    480 %      char *GetExceptionMessage(const int error)
    481 %
    482 %  A description of each parameter follows:
    483 %
    484 %    o error: the error code.
    485 %
    486 */
    487 MagickExport char *GetExceptionMessage(const int error)
    488 {
    489   char
    490     exception[MagickPathExtent];
    491 
    492   *exception='\0';
    493 #if defined(MAGICKCORE_HAVE_STRERROR_R)
    494 #if !defined(MAGICKCORE_STRERROR_R_CHAR_P)
    495   (void) strerror_r(error,exception,sizeof(exception));
    496 #else
    497   (void) CopyMagickString(exception,strerror_r(error,exception,
    498     sizeof(exception)),sizeof(exception));
    499 #endif
    500 #else
    501   (void) CopyMagickString(exception,strerror(error),sizeof(exception));
    502 #endif
    503   return(ConstantString(exception));
    504 }
    505 
    506 /*
    508 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    509 %                                                                             %
    510 %                                                                             %
    511 %                                                                             %
    512 %   G e t L o c a l e E x c e p t i o n M e s s a g e                         %
    513 %                                                                             %
    514 %                                                                             %
    515 %                                                                             %
    516 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    517 %
    518 %  GetLocaleExceptionMessage() converts a enumerated exception severity and tag
    519 %  to a message in the current locale.
    520 %
    521 %  The format of the GetLocaleExceptionMessage method is:
    522 %
    523 %      const char *GetLocaleExceptionMessage(const ExceptionType severity,
    524 %        const char *tag)
    525 %
    526 %  A description of each parameter follows:
    527 %
    528 %    o severity: the severity of the exception.
    529 %
    530 %    o tag: the message tag.
    531 %
    532 */
    533 
    534 static const char *ExceptionSeverityToTag(const ExceptionType severity)
    535 {
    536   switch (severity)
    537   {
    538     case ResourceLimitWarning: return("Resource/Limit/Warning/");
    539     case TypeWarning: return("Type/Warning/");
    540     case OptionWarning: return("Option/Warning/");
    541     case DelegateWarning: return("Delegate/Warning/");
    542     case MissingDelegateWarning: return("Missing/Delegate/Warning/");
    543     case CorruptImageWarning: return("Corrupt/Image/Warning/");
    544     case FileOpenWarning: return("File/Open/Warning/");
    545     case BlobWarning: return("Blob/Warning/");
    546     case StreamWarning: return("Stream/Warning/");
    547     case CacheWarning: return("Cache/Warning/");
    548     case CoderWarning: return("Coder/Warning/");
    549     case FilterWarning: return("Filter/Warning/");
    550     case ModuleWarning: return("Module/Warning/");
    551     case DrawWarning: return("Draw/Warning/");
    552     case ImageWarning: return("Image/Warning/");
    553     case WandWarning: return("Wand/Warning/");
    554     case XServerWarning: return("XServer/Warning/");
    555     case MonitorWarning: return("Monitor/Warning/");
    556     case RegistryWarning: return("Registry/Warning/");
    557     case ConfigureWarning: return("Configure/Warning/");
    558     case PolicyWarning: return("Policy/Warning/");
    559     case ResourceLimitError: return("Resource/Limit/Error/");
    560     case TypeError: return("Type/Error/");
    561     case OptionError: return("Option/Error/");
    562     case DelegateError: return("Delegate/Error/");
    563     case MissingDelegateError: return("Missing/Delegate/Error/");
    564     case CorruptImageError: return("Corrupt/Image/Error/");
    565     case FileOpenError: return("File/Open/Error/");
    566     case BlobError: return("Blob/Error/");
    567     case StreamError: return("Stream/Error/");
    568     case CacheError: return("Cache/Error/");
    569     case CoderError: return("Coder/Error/");
    570     case FilterError: return("Filter/Error/");
    571     case ModuleError: return("Module/Error/");
    572     case DrawError: return("Draw/Error/");
    573     case ImageError: return("Image/Error/");
    574     case WandError: return("Wand/Error/");
    575     case XServerError: return("XServer/Error/");
    576     case MonitorError: return("Monitor/Error/");
    577     case RegistryError: return("Registry/Error/");
    578     case ConfigureError: return("Configure/Error/");
    579     case PolicyError: return("Policy/Error/");
    580     case ResourceLimitFatalError: return("Resource/Limit/FatalError/");
    581     case TypeFatalError: return("Type/FatalError/");
    582     case OptionFatalError: return("Option/FatalError/");
    583     case DelegateFatalError: return("Delegate/FatalError/");
    584     case MissingDelegateFatalError: return("Missing/Delegate/FatalError/");
    585     case CorruptImageFatalError: return("Corrupt/Image/FatalError/");
    586     case FileOpenFatalError: return("File/Open/FatalError/");
    587     case BlobFatalError: return("Blob/FatalError/");
    588     case StreamFatalError: return("Stream/FatalError/");
    589     case CacheFatalError: return("Cache/FatalError/");
    590     case CoderFatalError: return("Coder/FatalError/");
    591     case FilterFatalError: return("Filter/FatalError/");
    592     case ModuleFatalError: return("Module/FatalError/");
    593     case DrawFatalError: return("Draw/FatalError/");
    594     case ImageFatalError: return("Image/FatalError/");
    595     case WandFatalError: return("Wand/FatalError/");
    596     case XServerFatalError: return("XServer/FatalError/");
    597     case MonitorFatalError: return("Monitor/FatalError/");
    598     case RegistryFatalError: return("Registry/FatalError/");
    599     case ConfigureFatalError: return("Configure/FatalError/");
    600     case PolicyFatalError: return("Policy/FatalError/");
    601     default: break;
    602   }
    603   return("");
    604 }
    605 
    606 MagickExport const char *GetLocaleExceptionMessage(const ExceptionType severity,
    607   const char *tag)
    608 {
    609   char
    610     message[MagickPathExtent];
    611 
    612   const char
    613     *locale_message;
    614 
    615   assert(tag != (const char *) NULL);
    616   (void) FormatLocaleString(message,MagickPathExtent,"Exception/%s%s",
    617     ExceptionSeverityToTag(severity),tag);
    618   locale_message=GetLocaleMessage(message);
    619   if (locale_message == (const char *) NULL)
    620     return(tag);
    621   if (locale_message == message)
    622     return(tag);
    623   return(locale_message);
    624 }
    625 
    626 /*
    628 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    629 %                                                                             %
    630 %                                                                             %
    631 %                                                                             %
    632 %   I n h e r i t E x c e p t i o n                                           %
    633 %                                                                             %
    634 %                                                                             %
    635 %                                                                             %
    636 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    637 %
    638 %  InheritException() inherits an exception from a related exception.
    639 %
    640 %  The format of the InheritException method is:
    641 %
    642 %      InheritException(ExceptionInfo *exception,const ExceptionInfo *relative)
    643 %
    644 %  A description of each parameter follows:
    645 %
    646 %    o exception: the exception info.
    647 %
    648 %    o relative: the related exception info.
    649 %
    650 */
    651 MagickExport void InheritException(ExceptionInfo *exception,
    652   const ExceptionInfo *relative)
    653 {
    654   register const ExceptionInfo
    655     *p;
    656 
    657   assert(exception != (ExceptionInfo *) NULL);
    658   assert(exception->signature == MagickCoreSignature);
    659   assert(relative != (ExceptionInfo *) NULL);
    660   assert(relative->signature == MagickCoreSignature);
    661   assert(exception != relative);
    662   if (relative->exceptions == (void *) NULL)
    663     return;
    664   LockSemaphoreInfo(relative->semaphore);
    665   ResetLinkedListIterator((LinkedListInfo *) relative->exceptions);
    666   p=(const ExceptionInfo *) GetNextValueInLinkedList((LinkedListInfo *)
    667     relative->exceptions);
    668   while (p != (const ExceptionInfo *) NULL)
    669   {
    670     (void) ThrowException(exception,p->severity,p->reason,p->description);
    671     p=(const ExceptionInfo *) GetNextValueInLinkedList((LinkedListInfo *)
    672       relative->exceptions);
    673   }
    674   UnlockSemaphoreInfo(relative->semaphore);
    675 }
    676 
    677 /*
    679 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    680 %                                                                             %
    681 %                                                                             %
    682 %                                                                             %
    683 %   I n i t i a l i z e t E x c e p t i o n I n f o                           %
    684 %                                                                             %
    685 %                                                                             %
    686 %                                                                             %
    687 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    688 %
    689 %  InitializeExceptionInfo() initializes an exception to default values.
    690 %
    691 %  The format of the InitializeExceptionInfo method is:
    692 %
    693 %      InitializeExceptionInfo(ExceptionInfo *exception)
    694 %
    695 %  A description of each parameter follows:
    696 %
    697 %    o exception: the exception info.
    698 %
    699 */
    700 MagickPrivate void InitializeExceptionInfo(ExceptionInfo *exception)
    701 {
    702   assert(exception != (ExceptionInfo *) NULL);
    703   (void) ResetMagickMemory(exception,0,sizeof(*exception));
    704   exception->severity=UndefinedException;
    705   exception->exceptions=(void *) NewLinkedList(0);
    706   exception->semaphore=AcquireSemaphoreInfo();
    707   exception->signature=MagickCoreSignature;
    708 }
    709 
    710 /*
    712 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    713 %                                                                             %
    714 %                                                                             %
    715 %                                                                             %
    716 %   M a g i c k E r r o r                                                     %
    717 %                                                                             %
    718 %                                                                             %
    719 %                                                                             %
    720 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    721 %
    722 %  MagickError() calls the exception handler methods with an error reason.
    723 %
    724 %  The format of the MagickError method is:
    725 %
    726 %      void MagickError(const ExceptionType error,const char *reason,
    727 %        const char *description)
    728 %
    729 %  A description of each parameter follows:
    730 %
    731 %    o exception: Specifies the numeric error category.
    732 %
    733 %    o reason: Specifies the reason to display before terminating the
    734 %      program.
    735 %
    736 %    o description: Specifies any description to the reason.
    737 %
    738 */
    739 MagickExport void MagickError(const ExceptionType error,const char *reason,
    740   const char *description)
    741 {
    742   if (error_handler != (ErrorHandler) NULL)
    743     (*error_handler)(error,reason,description);
    744 }
    745 
    746 /*
    748 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    749 %                                                                             %
    750 %                                                                             %
    751 %                                                                             %
    752 %   M a g i c k F a t al E r r o r                                            %
    753 %                                                                             %
    754 %                                                                             %
    755 %                                                                             %
    756 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    757 %
    758 %  MagickFatalError() calls the fatal exception handler methods with an error
    759 %  reason.
    760 %
    761 %  The format of the MagickError method is:
    762 %
    763 %      void MagickFatalError(const ExceptionType error,const char *reason,
    764 %        const char *description)
    765 %
    766 %  A description of each parameter follows:
    767 %
    768 %    o exception: Specifies the numeric error category.
    769 %
    770 %    o reason: Specifies the reason to display before terminating the
    771 %      program.
    772 %
    773 %    o description: Specifies any description to the reason.
    774 %
    775 */
    776 MagickExport void MagickFatalError(const ExceptionType error,const char *reason,
    777   const char *description)
    778 {
    779   if (fatal_error_handler != (ErrorHandler) NULL)
    780     (*fatal_error_handler)(error,reason,description);
    781 }
    782 
    783 /*
    785 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    786 %                                                                             %
    787 %                                                                             %
    788 %                                                                             %
    789 %   M a g i c k W a r n i n g                                                 %
    790 %                                                                             %
    791 %                                                                             %
    792 %                                                                             %
    793 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    794 %
    795 %  MagickWarning() calls the warning handler methods with a warning reason.
    796 %
    797 %  The format of the MagickWarning method is:
    798 %
    799 %      void MagickWarning(const ExceptionType warning,const char *reason,
    800 %        const char *description)
    801 %
    802 %  A description of each parameter follows:
    803 %
    804 %    o warning: the warning severity.
    805 %
    806 %    o reason: Define the reason for the warning.
    807 %
    808 %    o description: Describe the warning.
    809 %
    810 */
    811 MagickExport void MagickWarning(const ExceptionType warning,const char *reason,
    812   const char *description)
    813 {
    814   if (warning_handler != (WarningHandler) NULL)
    815     (*warning_handler)(warning,reason,description);
    816 }
    817 
    818 /*
    820 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    821 %                                                                             %
    822 %                                                                             %
    823 %                                                                             %
    824 %   S e t E r r o r H a n d l e r                                             %
    825 %                                                                             %
    826 %                                                                             %
    827 %                                                                             %
    828 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    829 %
    830 %  SetErrorHandler() sets the exception handler to the specified method
    831 %  and returns the previous exception handler.
    832 %
    833 %  The format of the SetErrorHandler method is:
    834 %
    835 %      ErrorHandler SetErrorHandler(ErrorHandler handler)
    836 %
    837 %  A description of each parameter follows:
    838 %
    839 %    o handler: the method to handle errors.
    840 %
    841 */
    842 MagickExport ErrorHandler SetErrorHandler(ErrorHandler handler)
    843 {
    844   ErrorHandler
    845     previous_handler;
    846 
    847   previous_handler=error_handler;
    848   error_handler=handler;
    849   return(previous_handler);
    850 }
    851 
    852 /*
    854 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    855 %                                                                             %
    856 %                                                                             %
    857 %                                                                             %
    858 %   S e t F a t a l E r r o r H a n d l e r                                   %
    859 %                                                                             %
    860 %                                                                             %
    861 %                                                                             %
    862 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    863 %
    864 %  SetFatalErrorHandler() sets the fatal exception handler to the specified
    865 %  method and returns the previous fatal exception handler.
    866 %
    867 %  The format of the SetErrorHandler method is:
    868 %
    869 %      ErrorHandler SetErrorHandler(ErrorHandler handler)
    870 %
    871 %  A description of each parameter follows:
    872 %
    873 %    o handler: the method to handle errors.
    874 %
    875 */
    876 MagickExport FatalErrorHandler SetFatalErrorHandler(FatalErrorHandler handler)
    877 {
    878   FatalErrorHandler
    879     previous_handler;
    880 
    881   previous_handler=fatal_error_handler;
    882   fatal_error_handler=handler;
    883   return(previous_handler);
    884 }
    885 
    886 /*
    888 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    889 %                                                                             %
    890 %                                                                             %
    891 %                                                                             %
    892 %   S e t W a r n i n g H a n d l e r                                         %
    893 %                                                                             %
    894 %                                                                             %
    895 %                                                                             %
    896 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    897 %
    898 %  SetWarningHandler() sets the warning handler to the specified method
    899 %  and returns the previous warning handler.
    900 %
    901 %  The format of the SetWarningHandler method is:
    902 %
    903 %      ErrorHandler SetWarningHandler(ErrorHandler handler)
    904 %
    905 %  A description of each parameter follows:
    906 %
    907 %    o handler: the method to handle warnings.
    908 %
    909 */
    910 MagickExport WarningHandler SetWarningHandler(WarningHandler handler)
    911 {
    912   WarningHandler
    913     previous_handler;
    914 
    915   previous_handler=warning_handler;
    916   warning_handler=handler;
    917   return(previous_handler);
    918 }
    919 
    920 /*
    922 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    923 %                                                                             %
    924 %                                                                             %
    925 %                                                                             %
    926 %   T h r o w E x c e p t i o n                                               %
    927 %                                                                             %
    928 %                                                                             %
    929 %                                                                             %
    930 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    931 %
    932 %  ThrowException() throws an exception with the specified severity code,
    933 %  reason, and optional description.
    934 %
    935 %  The format of the ThrowException method is:
    936 %
    937 %      MagickBooleanType ThrowException(ExceptionInfo *exception,
    938 %        const ExceptionType severity,const char *reason,
    939 %        const char *description)
    940 %
    941 %  A description of each parameter follows:
    942 %
    943 %    o exception: the exception info.
    944 %
    945 %    o severity: the severity of the exception.
    946 %
    947 %    o reason: the reason for the exception.
    948 %
    949 %    o description: the exception description.
    950 %
    951 */
    952 MagickExport MagickBooleanType ThrowException(ExceptionInfo *exception,
    953   const ExceptionType severity,const char *reason,const char *description)
    954 {
    955   register ExceptionInfo
    956     *p;
    957 
    958   assert(exception != (ExceptionInfo *) NULL);
    959   assert(exception->signature == MagickCoreSignature);
    960   LockSemaphoreInfo(exception->semaphore);
    961   p=(ExceptionInfo *) GetLastValueInLinkedList((LinkedListInfo *)
    962     exception->exceptions);
    963   if ((p != (ExceptionInfo *) NULL) && (p->severity == severity) &&
    964       (LocaleCompare(exception->reason,reason) == 0) &&
    965       (LocaleCompare(exception->description,description) == 0))
    966     {
    967       UnlockSemaphoreInfo(exception->semaphore);
    968       return(MagickTrue);
    969     }
    970   p=(ExceptionInfo *) AcquireMagickMemory(sizeof(*p));
    971   if (p == (ExceptionInfo *) NULL)
    972     {
    973       UnlockSemaphoreInfo(exception->semaphore);
    974       ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
    975     }
    976   (void) ResetMagickMemory(p,0,sizeof(*p));
    977   p->severity=severity;
    978   if (reason != (const char *) NULL)
    979     p->reason=ConstantString(reason);
    980   if (description != (const char *) NULL)
    981     p->description=ConstantString(description);
    982   p->signature=MagickCoreSignature;
    983   (void) AppendValueToLinkedList((LinkedListInfo *) exception->exceptions,p);
    984   if (p->severity >= exception->severity)
    985     {
    986       exception->severity=p->severity;
    987       exception->reason=p->reason;
    988       exception->description=p->description;
    989     }
    990   UnlockSemaphoreInfo(exception->semaphore);
    991   return(MagickTrue);
    992 }
    993 
    994 /*
    996 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    997 %                                                                             %
    998 %                                                                             %
    999 %                                                                             %
   1000 %   T h r o w M a g i c k E x c e p t i o n                                   %
   1001 %                                                                             %
   1002 %                                                                             %
   1003 %                                                                             %
   1004 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1005 %
   1006 %  ThrowMagickException logs an exception as determined by the log
   1007 %  configuration file.  If an error occurs, MagickFalse is returned
   1008 %  otherwise MagickTrue.
   1009 %
   1010 %  The format of the ThrowMagickException method is:
   1011 %
   1012 %      MagickBooleanType ThrowFileException(ExceptionInfo *exception,
   1013 %        const char *module,const char *function,const size_t line,
   1014 %        const ExceptionType severity,const char *tag,const char *format,...)
   1015 %
   1016 %  A description of each parameter follows:
   1017 %
   1018 %    o exception: the exception info.
   1019 %
   1020 %    o filename: the source module filename.
   1021 %
   1022 %    o function: the function name.
   1023 %
   1024 %    o line: the line number of the source module.
   1025 %
   1026 %    o severity: Specifies the numeric error category.
   1027 %
   1028 %    o tag: the locale tag.
   1029 %
   1030 %    o format: the output format.
   1031 %
   1032 */
   1033 
   1034 MagickExport MagickBooleanType ThrowMagickExceptionList(
   1035   ExceptionInfo *exception,const char *module,const char *function,
   1036   const size_t line,const ExceptionType severity,const char *tag,
   1037   const char *format,va_list operands)
   1038 {
   1039   char
   1040     message[MagickPathExtent],
   1041     path[MagickPathExtent],
   1042     reason[MagickPathExtent];
   1043 
   1044   const char
   1045     *locale,
   1046     *type;
   1047 
   1048   int
   1049     n;
   1050 
   1051   MagickBooleanType
   1052     status;
   1053 
   1054   size_t
   1055     length;
   1056 
   1057   assert(exception != (ExceptionInfo *) NULL);
   1058   assert(exception->signature == MagickCoreSignature);
   1059   locale=GetLocaleExceptionMessage(severity,tag);
   1060   (void) CopyMagickString(reason,locale,MagickPathExtent);
   1061   (void) ConcatenateMagickString(reason," ",MagickPathExtent);
   1062   length=strlen(reason);
   1063 #if defined(MAGICKCORE_HAVE_VSNPRINTF)
   1064   n=vsnprintf(reason+length,MagickPathExtent-length,format,operands);
   1065 #else
   1066   n=vsprintf(reason+length,format,operands);
   1067 #endif
   1068   if (n < 0)
   1069     reason[MagickPathExtent-1]='\0';
   1070   status=LogMagickEvent(ExceptionEvent,module,function,line,"%s",reason);
   1071   GetPathComponent(module,TailPath,path);
   1072   type="undefined";
   1073   if ((severity >= WarningException) && (severity < ErrorException))
   1074     type="warning";
   1075   if ((severity >= ErrorException) && (severity < FatalErrorException))
   1076     type="error";
   1077   if (severity >= FatalErrorException)
   1078     type="fatal";
   1079   (void) FormatLocaleString(message,MagickPathExtent,"%s @ %s/%s/%s/%.20g",reason,
   1080     type,path,function,(double) line);
   1081   (void) ThrowException(exception,severity,message,(char *) NULL);
   1082   return(status);
   1083 }
   1084 
   1085 MagickExport MagickBooleanType ThrowMagickException(ExceptionInfo *exception,
   1086   const char *module,const char *function,const size_t line,
   1087   const ExceptionType severity,const char *tag,const char *format,...)
   1088 {
   1089   MagickBooleanType
   1090     status;
   1091 
   1092   va_list
   1093     operands;
   1094 
   1095   va_start(operands,format);
   1096   status=ThrowMagickExceptionList(exception,module,function,line,severity,tag,
   1097     format,operands);
   1098   va_end(operands);
   1099   return(status);
   1100 }
   1101