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