]> granicus.if.org Git - imagemagick/blob - MagickCore/exception.c
Fixed detection of Ghostscript location.
[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-2014 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 \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/hashmap.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 static ErrorHandler
76   error_handler = DefaultErrorHandler;
77
78 static FatalErrorHandler
79   fatal_error_handler = DefaultFatalErrorHandler;
80
81 static WarningHandler
82   warning_handler = DefaultWarningHandler;
83 \f
84 /*
85 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
86 %                                                                             %
87 %                                                                             %
88 %                                                                             %
89 %   A c q u i r e E x c e p t i o n I n f o                                   %
90 %                                                                             %
91 %                                                                             %
92 %                                                                             %
93 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
94 %
95 %  AcquireExceptionInfo() allocates the ExceptionInfo structure.
96 %
97 %  The format of the AcquireExceptionInfo method is:
98 %
99 %      ExceptionInfo *AcquireExceptionInfo(void)
100 %
101 */
102 MagickExport ExceptionInfo *AcquireExceptionInfo(void)
103 {
104   ExceptionInfo
105     *exception;
106
107   exception=(ExceptionInfo *) AcquireMagickMemory(sizeof(*exception));
108   if (exception == (ExceptionInfo *) NULL)
109     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
110   GetExceptionInfo(exception);
111   exception->relinquish=MagickTrue;
112   return(exception);
113 }
114 \f
115 /*
116 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
117 %                                                                             %
118 %                                                                             %
119 %                                                                             %
120 %   C l e a r M a g i c k E x c e p t i o n                                   %
121 %                                                                             %
122 %                                                                             %
123 %                                                                             %
124 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
125 %
126 %  ClearMagickException() clears any exception that may not have been caught
127 %  yet.
128 %
129 %  The format of the ClearMagickException method is:
130 %
131 %      ClearMagickException(ExceptionInfo *exception)
132 %
133 %  A description of each parameter follows:
134 %
135 %    o exception: the exception info.
136 %
137 */
138
139 static void *DestroyExceptionElement(void *exception)
140 {
141   register ExceptionInfo
142     *p;
143
144   p=(ExceptionInfo *) exception;
145   if (p->reason != (char *) NULL)
146     p->reason=DestroyString(p->reason);
147   if (p->description != (char *) NULL)
148     p->description=DestroyString(p->description);
149   p=(ExceptionInfo *) RelinquishMagickMemory(p);
150   return((void *) NULL);
151 }
152
153 MagickExport void ClearMagickException(ExceptionInfo *exception)
154 {
155   register ExceptionInfo
156     *p;
157
158   assert(exception != (ExceptionInfo *) NULL);
159   assert(exception->signature == MagickSignature);
160   if (exception->exceptions  == (void *) NULL)
161     return;
162   LockSemaphoreInfo(exception->semaphore);
163   p=(ExceptionInfo *) RemoveLastElementFromLinkedList((LinkedListInfo *)
164     exception->exceptions);
165   while (p != (ExceptionInfo *) NULL)
166   {
167     (void) DestroyExceptionElement(p);
168     p=(ExceptionInfo *) RemoveLastElementFromLinkedList((LinkedListInfo *)
169       exception->exceptions);
170   }
171   exception->severity=UndefinedException;
172   exception->reason=(char *) NULL;
173   exception->description=(char *) NULL;
174   UnlockSemaphoreInfo(exception->semaphore);
175   errno=0;
176 }
177 \f
178 /*
179 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
180 %                                                                             %
181 %                                                                             %
182 %                                                                             %
183 %   C a t c h E x c e p t i o n                                               %
184 %                                                                             %
185 %                                                                             %
186 %                                                                             %
187 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
188 %
189 %  CatchException() returns if no exceptions is found otherwise it reports
190 %  the exception as a warning, error, or fatal depending on the severity.
191 %
192 %  The format of the CatchException method is:
193 %
194 %      CatchException(ExceptionInfo *exception)
195 %
196 %  A description of each parameter follows:
197 %
198 %    o exception: the exception info.
199 %
200 */
201 MagickExport void CatchException(ExceptionInfo *exception)
202 {
203   register const ExceptionInfo
204     *p;
205
206   assert(exception != (ExceptionInfo *) NULL);
207   assert(exception->signature == MagickSignature);
208   if (exception->exceptions  == (void *) NULL)
209     return;
210   LockSemaphoreInfo(exception->semaphore);
211   ResetLinkedListIterator((LinkedListInfo *) exception->exceptions);
212   p=(const ExceptionInfo *) GetNextValueInLinkedList((LinkedListInfo *)
213     exception->exceptions);
214   while (p != (const ExceptionInfo *) NULL)
215   {
216     if ((p->severity >= WarningException) && (p->severity < ErrorException))
217       MagickWarning(p->severity,p->reason,p->description);
218     if ((p->severity >= ErrorException) && (p->severity < FatalErrorException))
219       MagickError(p->severity,p->reason,p->description);
220     if (p->severity >= FatalErrorException)
221       MagickFatalError(p->severity,p->reason,p->description);
222     p=(const ExceptionInfo *) GetNextValueInLinkedList((LinkedListInfo *)
223       exception->exceptions);
224   }
225   UnlockSemaphoreInfo(exception->semaphore);
226   ClearMagickException(exception);
227 }
228 \f
229 /*
230 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
231 %                                                                             %
232 %                                                                             %
233 %                                                                             %
234 %   C l o n e E x c e p t i o n I n f o                                       %
235 %                                                                             %
236 %                                                                             %
237 %                                                                             %
238 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
239 %
240 %  CloneExceptionInfo() clones the ExceptionInfo structure.
241 %
242 %  The format of the CloneExceptionInfo method is:
243 %
244 %      ExceptionInfo *CloneException(ExceptionInfo *exception)
245 %
246 %  A description of each parameter follows:
247 %
248 %    o exception: the exception info.
249 %
250 */
251 MagickExport ExceptionInfo *CloneExceptionInfo(ExceptionInfo *exception)
252 {
253   ExceptionInfo
254     *clone_exception;
255
256   clone_exception=(ExceptionInfo *) AcquireMagickMemory(sizeof(*exception));
257   if (clone_exception == (ExceptionInfo *) NULL)
258     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
259   GetExceptionInfo(clone_exception);
260   InheritException(clone_exception,exception);
261   clone_exception->relinquish=MagickTrue;
262   return(clone_exception);
263 }
264 \f
265 /*
266 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
267 %                                                                             %
268 %                                                                             %
269 %                                                                             %
270 +   D e f a u l t E r r o r H a n d l e r                                     %
271 %                                                                             %
272 %                                                                             %
273 %                                                                             %
274 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
275 %
276 %  DefaultErrorHandler() displays an error reason.
277 %
278 %  The format of the DefaultErrorHandler method is:
279 %
280 %      void MagickError(const ExceptionType severity,const char *reason,
281 %        const char *description)
282 %
283 %  A description of each parameter follows:
284 %
285 %    o severity: Specifies the numeric error category.
286 %
287 %    o reason: Specifies the reason to display before terminating the
288 %      program.
289 %
290 %    o description: Specifies any description to the reason.
291 %
292 */
293 static void DefaultErrorHandler(const ExceptionType magick_unused(severity),
294   const char *reason,const char *description)
295 {
296   if (reason == (char *) NULL)
297     return;
298   (void) FormatLocaleFile(stderr,"%s: %s",GetClientName(),reason);
299   if (description != (char *) NULL)
300     (void) FormatLocaleFile(stderr," (%s)",description);
301   (void) FormatLocaleFile(stderr,".\n");
302   (void) fflush(stderr);
303 }
304 \f
305 /*
306 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
307 %                                                                             %
308 %                                                                             %
309 %                                                                             %
310 +   D e f a u l t F a t a l E r r o r H a n d l e r                           %
311 %                                                                             %
312 %                                                                             %
313 %                                                                             %
314 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
315 %
316 %  DefaultFatalErrorHandler() displays an error reason and then terminates the
317 %  program.
318 %
319 %  The format of the DefaultFatalErrorHandler method is:
320 %
321 %      void MagickFatalError(const ExceptionType severity,const char *reason,
322 %        const char *description)
323 %
324 %  A description of each parameter follows:
325 %
326 %    o severity: Specifies the numeric error category.
327 %
328 %    o reason: Specifies the reason to display before terminating the program.
329 %
330 %    o description: Specifies any description to the reason.
331 %
332 */
333 static void DefaultFatalErrorHandler(const ExceptionType severity,
334   const char *reason,const char *description)
335 {
336   if (reason == (char *) NULL)
337     return;
338   (void) FormatLocaleFile(stderr,"%s: %s",GetClientName(),reason);
339   if (description != (char *) NULL)
340     (void) FormatLocaleFile(stderr," (%s)",description);
341   (void) FormatLocaleFile(stderr,".\n");
342   (void) fflush(stderr);
343   MagickCoreTerminus();
344   exit((int) (severity-FatalErrorException)+1);
345 }
346 \f
347 /*
348 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
349 %                                                                             %
350 %                                                                             %
351 %                                                                             %
352 +   D e f a u l t W a r n i n g H a n d l e r                                 %
353 %                                                                             %
354 %                                                                             %
355 %                                                                             %
356 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
357 %
358 %  DefaultWarningHandler() displays a warning reason.
359 %
360 %  The format of the DefaultWarningHandler method is:
361 %
362 %      void DefaultWarningHandler(const ExceptionType severity,
363 %        const char *reason,const char *description)
364 %
365 %  A description of each parameter follows:
366 %
367 %    o severity: Specifies the numeric warning category.
368 %
369 %    o reason: Specifies the reason to display before terminating the
370 %      program.
371 %
372 %    o description: Specifies any description to the reason.
373 %
374 */
375 static void DefaultWarningHandler(const ExceptionType magick_unused(severity),
376   const char *reason,const char *description)
377 {
378   if (reason == (char *) NULL)
379     return;
380   (void) FormatLocaleFile(stderr,"%s: %s",GetClientName(),reason);
381   if (description != (char *) NULL)
382     (void) FormatLocaleFile(stderr," (%s)",description);
383   (void) FormatLocaleFile(stderr,".\n");
384   (void) fflush(stderr);
385 }
386 \f
387 /*
388 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
389 %                                                                             %
390 %                                                                             %
391 %                                                                             %
392 %   D e s t r o y E x c e p t i o n I n f o                                   %
393 %                                                                             %
394 %                                                                             %
395 %                                                                             %
396 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
397 %
398 %  DestroyExceptionInfo() deallocates memory associated with an exception.
399 %
400 %  The format of the DestroyExceptionInfo method is:
401 %
402 %      ExceptionInfo *DestroyExceptionInfo(ExceptionInfo *exception)
403 %
404 %  A description of each parameter follows:
405 %
406 %    o exception: the exception info.
407 %
408 */
409 MagickExport ExceptionInfo *DestroyExceptionInfo(ExceptionInfo *exception)
410 {
411   MagickBooleanType
412     relinquish;
413
414   assert(exception != (ExceptionInfo *) NULL);
415   assert(exception->signature == MagickSignature);
416   if (exception->semaphore == (SemaphoreInfo *) NULL)
417     ActivateSemaphoreInfo(&exception->semaphore);
418   LockSemaphoreInfo(exception->semaphore);
419   exception->severity=UndefinedException;
420   if (exception->exceptions != (void *) NULL)
421     exception->exceptions=(void *) DestroyLinkedList((LinkedListInfo *)
422       exception->exceptions,DestroyExceptionElement);
423   relinquish=exception->relinquish;
424   if (exception->relinquish != MagickFalse)
425     exception->signature=(~MagickSignature);
426   UnlockSemaphoreInfo(exception->semaphore);
427   RelinquishSemaphoreInfo(&exception->semaphore);
428   if (relinquish != MagickFalse)
429     exception=(ExceptionInfo *) RelinquishMagickMemory(exception);
430   return(exception);
431 }
432 \f
433 /*
434 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
435 %                                                                             %
436 %                                                                             %
437 %                                                                             %
438 %   G e t E x c e p t i o n I n f o                                           %
439 %                                                                             %
440 %                                                                             %
441 %                                                                             %
442 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
443 %
444 %  GetExceptionInfo() initializes an exception to default values.
445 %
446 %  The format of the GetExceptionInfo method is:
447 %
448 %      GetExceptionInfo(ExceptionInfo *exception)
449 %
450 %  A description of each parameter follows:
451 %
452 %    o exception: the exception info.
453 %
454 */
455 MagickExport void GetExceptionInfo(ExceptionInfo *exception)
456 {
457   assert(exception != (ExceptionInfo *) NULL);
458   (void) ResetMagickMemory(exception,0,sizeof(*exception));
459   exception->severity=UndefinedException;
460   exception->exceptions=(void *) NewLinkedList(0);
461   exception->semaphore=AcquireSemaphoreInfo();
462   exception->signature=MagickSignature;
463 }
464 \f
465 /*
466 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
467 %                                                                             %
468 %                                                                             %
469 %                                                                             %
470 %   G e t E x c e p t i o n M e s s a g e                                     %
471 %                                                                             %
472 %                                                                             %
473 %                                                                             %
474 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
475 %
476 %  GetExceptionMessage() returns the error message defined by the specified
477 %  error code.
478 %
479 %  The format of the GetExceptionMessage method is:
480 %
481 %      char *GetExceptionMessage(const int error)
482 %
483 %  A description of each parameter follows:
484 %
485 %    o error: the error code.
486 %
487 */
488 MagickExport char *GetExceptionMessage(const int error)
489 {
490   char
491     exception[MaxTextExtent];
492
493   *exception='\0';
494 #if defined(MAGICKCORE_HAVE_STRERROR_R)
495 #if !defined(MAGICKCORE_STRERROR_R_CHAR_P)
496   (void) strerror_r(error,exception,sizeof(exception));
497 #else
498   (void) CopyMagickString(exception,strerror_r(error,exception,
499     sizeof(exception)),sizeof(exception));
500 #endif
501 #else
502   (void) CopyMagickString(exception,strerror(error),sizeof(exception));
503 #endif
504   return(ConstantString(exception));
505 }
506 \f
507 /*
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[MaxTextExtent];
611
612   const char
613     *locale_message;
614
615   assert(tag != (const char *) NULL);
616   (void) FormatLocaleString(message,MaxTextExtent,"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 \f
626 /*
627 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
628 %                                                                             %
629 %                                                                             %
630 %                                                                             %
631 %   I n h e r i t E x c e p t i o n                                           %
632 %                                                                             %
633 %                                                                             %
634 %                                                                             %
635 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
636 %
637 %  InheritException() inherits an exception from a related exception.
638 %
639 %  The format of the InheritException method is:
640 %
641 %      InheritException(ExceptionInfo *exception,const ExceptionInfo *relative)
642 %
643 %  A description of each parameter follows:
644 %
645 %    o exception: the exception info.
646 %
647 %    o relative: the related exception info.
648 %
649 */
650 MagickExport void InheritException(ExceptionInfo *exception,
651   const ExceptionInfo *relative)
652 {
653   register const ExceptionInfo
654     *p;
655
656   assert(exception != (ExceptionInfo *) NULL);
657   assert(exception->signature == MagickSignature);
658   assert(relative != (ExceptionInfo *) NULL);
659   assert(relative->signature == MagickSignature);
660   if (relative->exceptions == (void *) NULL)
661     return;
662   LockSemaphoreInfo(relative->semaphore);
663   ResetLinkedListIterator((LinkedListInfo *) relative->exceptions);
664   p=(const ExceptionInfo *) GetNextValueInLinkedList((LinkedListInfo *)
665     relative->exceptions);
666   while (p != (const ExceptionInfo *) NULL)
667   {
668     (void) ThrowException(exception,p->severity,p->reason,p->description);
669     p=(const ExceptionInfo *) GetNextValueInLinkedList((LinkedListInfo *)
670       relative->exceptions);
671   }
672   UnlockSemaphoreInfo(relative->semaphore);
673 }
674 \f
675 /*
676 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
677 %                                                                             %
678 %                                                                             %
679 %                                                                             %
680 %   M a g i c k E r r o r                                                     %
681 %                                                                             %
682 %                                                                             %
683 %                                                                             %
684 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
685 %
686 %  MagickError() calls the exception handler methods with an error reason.
687 %
688 %  The format of the MagickError method is:
689 %
690 %      void MagickError(const ExceptionType error,const char *reason,
691 %        const char *description)
692 %
693 %  A description of each parameter follows:
694 %
695 %    o exception: Specifies the numeric error category.
696 %
697 %    o reason: Specifies the reason to display before terminating the
698 %      program.
699 %
700 %    o description: Specifies any description to the reason.
701 %
702 */
703 MagickExport void MagickError(const ExceptionType error,const char *reason,
704   const char *description)
705 {
706   if (error_handler != (ErrorHandler) NULL)
707     (*error_handler)(error,reason,description);
708 }
709 \f
710 /*
711 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
712 %                                                                             %
713 %                                                                             %
714 %                                                                             %
715 %   M a g i c k F a t al E r r o r                                            %
716 %                                                                             %
717 %                                                                             %
718 %                                                                             %
719 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
720 %
721 %  MagickFatalError() calls the fatal exception handler methods with an error
722 %  reason.
723 %
724 %  The format of the MagickError method is:
725 %
726 %      void MagickFatalError(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 MagickFatalError(const ExceptionType error,const char *reason,
740   const char *description)
741 {
742   if (fatal_error_handler != (ErrorHandler) NULL)
743     (*fatal_error_handler)(error,reason,description);
744 }
745 \f
746 /*
747 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
748 %                                                                             %
749 %                                                                             %
750 %                                                                             %
751 %   M a g i c k W a r n i n g                                                 %
752 %                                                                             %
753 %                                                                             %
754 %                                                                             %
755 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
756 %
757 %  MagickWarning() calls the warning handler methods with a warning reason.
758 %
759 %  The format of the MagickWarning method is:
760 %
761 %      void MagickWarning(const ExceptionType warning,const char *reason,
762 %        const char *description)
763 %
764 %  A description of each parameter follows:
765 %
766 %    o warning: the warning severity.
767 %
768 %    o reason: Define the reason for the warning.
769 %
770 %    o description: Describe the warning.
771 %
772 */
773 MagickExport void MagickWarning(const ExceptionType warning,const char *reason,
774   const char *description)
775 {
776   if (warning_handler != (WarningHandler) NULL)
777     (*warning_handler)(warning,reason,description);
778 }
779 \f
780 /*
781 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
782 %                                                                             %
783 %                                                                             %
784 %                                                                             %
785 %   S e t E r r o r H a n d l e r                                             %
786 %                                                                             %
787 %                                                                             %
788 %                                                                             %
789 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
790 %
791 %  SetErrorHandler() sets the exception handler to the specified method
792 %  and returns the previous exception handler.
793 %
794 %  The format of the SetErrorHandler method is:
795 %
796 %      ErrorHandler SetErrorHandler(ErrorHandler handler)
797 %
798 %  A description of each parameter follows:
799 %
800 %    o handler: the method to handle errors.
801 %
802 */
803 MagickExport ErrorHandler SetErrorHandler(ErrorHandler handler)
804 {
805   ErrorHandler
806     previous_handler;
807
808   previous_handler=error_handler;
809   error_handler=handler;
810   return(previous_handler);
811 }
812 \f
813 /*
814 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
815 %                                                                             %
816 %                                                                             %
817 %                                                                             %
818 %   S e t F a t a l E r r o r H a n d l e r                                   %
819 %                                                                             %
820 %                                                                             %
821 %                                                                             %
822 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
823 %
824 %  SetFatalErrorHandler() sets the fatal exception handler to the specified
825 %  method and returns the previous fatal exception handler.
826 %
827 %  The format of the SetErrorHandler method is:
828 %
829 %      ErrorHandler SetErrorHandler(ErrorHandler handler)
830 %
831 %  A description of each parameter follows:
832 %
833 %    o handler: the method to handle errors.
834 %
835 */
836 MagickExport FatalErrorHandler SetFatalErrorHandler(FatalErrorHandler handler)
837 {
838   FatalErrorHandler
839     previous_handler;
840
841   previous_handler=fatal_error_handler;
842   fatal_error_handler=handler;
843   return(previous_handler);
844 }
845 \f
846 /*
847 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
848 %                                                                             %
849 %                                                                             %
850 %                                                                             %
851 %   S e t W a r n i n g H a n d l e r                                         %
852 %                                                                             %
853 %                                                                             %
854 %                                                                             %
855 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
856 %
857 %  SetWarningHandler() sets the warning handler to the specified method
858 %  and returns the previous warning handler.
859 %
860 %  The format of the SetWarningHandler method is:
861 %
862 %      ErrorHandler SetWarningHandler(ErrorHandler handler)
863 %
864 %  A description of each parameter follows:
865 %
866 %    o handler: the method to handle warnings.
867 %
868 */
869 MagickExport WarningHandler SetWarningHandler(WarningHandler handler)
870 {
871   WarningHandler
872     previous_handler;
873
874   previous_handler=warning_handler;
875   warning_handler=handler;
876   return(previous_handler);
877 }
878 \f
879 /*
880 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
881 %                                                                             %
882 %                                                                             %
883 %                                                                             %
884 %   T h r o w E x c e p t i o n                                               %
885 %                                                                             %
886 %                                                                             %
887 %                                                                             %
888 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
889 %
890 %  ThrowException() throws an exception with the specified severity code,
891 %  reason, and optional description.
892 %
893 %  The format of the ThrowException method is:
894 %
895 %      MagickBooleanType ThrowException(ExceptionInfo *exception,
896 %        const ExceptionType severity,const char *reason,
897 %        const char *description)
898 %
899 %  A description of each parameter follows:
900 %
901 %    o exception: the exception info.
902 %
903 %    o severity: the severity of the exception.
904 %
905 %    o reason: the reason for the exception.
906 %
907 %    o description: the exception description.
908 %
909 */
910 MagickExport MagickBooleanType ThrowException(ExceptionInfo *exception,
911   const ExceptionType severity,const char *reason,const char *description)
912 {
913   register ExceptionInfo
914     *p;
915
916   assert(exception != (ExceptionInfo *) NULL);
917   assert(exception->signature == MagickSignature);
918   LockSemaphoreInfo(exception->semaphore);
919   p=(ExceptionInfo *) GetLastValueInLinkedList((LinkedListInfo *)
920     exception->exceptions);
921   if ((p != (ExceptionInfo *) NULL) && (p->severity == severity) &&
922       (LocaleCompare(exception->reason,reason) == 0) &&
923       (LocaleCompare(exception->description,description) == 0))
924     {
925       UnlockSemaphoreInfo(exception->semaphore);
926       return(MagickTrue);
927     }
928   p=(ExceptionInfo *) AcquireMagickMemory(sizeof(*p));
929   if (p == (ExceptionInfo *) NULL)
930     {
931       UnlockSemaphoreInfo(exception->semaphore);
932       ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
933     }
934   (void) ResetMagickMemory(p,0,sizeof(*p));
935   p->severity=severity;
936   if (reason != (const char *) NULL)
937     p->reason=ConstantString(reason);
938   if (description != (const char *) NULL)
939     p->description=ConstantString(description);
940   p->signature=MagickSignature;
941   (void) AppendValueToLinkedList((LinkedListInfo *) exception->exceptions,p);
942   if (p->severity >= exception->severity)
943     {
944       exception->severity=p->severity;
945       exception->reason=p->reason;
946       exception->description=p->description;
947     }
948   UnlockSemaphoreInfo(exception->semaphore);
949   return(MagickTrue);
950 }
951 \f
952 /*
953 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
954 %                                                                             %
955 %                                                                             %
956 %                                                                             %
957 %   T h r o w M a g i c k E x c e p t i o n                                   %
958 %                                                                             %
959 %                                                                             %
960 %                                                                             %
961 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
962 %
963 %  ThrowMagickException logs an exception as determined by the log
964 %  configuration file.  If an error occurs, MagickFalse is returned
965 %  otherwise MagickTrue.
966 %
967 %  The format of the ThrowMagickException method is:
968 %
969 %      MagickBooleanType ThrowFileException(ExceptionInfo *exception,
970 %        const char *module,const char *function,const size_t line,
971 %        const ExceptionType severity,const char *tag,const char *format,...)
972 %
973 %  A description of each parameter follows:
974 %
975 %    o exception: the exception info.
976 %
977 %    o filename: the source module filename.
978 %
979 %    o function: the function name.
980 %
981 %    o line: the line number of the source module.
982 %
983 %    o severity: Specifies the numeric error category.
984 %
985 %    o tag: the locale tag.
986 %
987 %    o format: the output format.
988 %
989 */
990
991 MagickExport MagickBooleanType ThrowMagickExceptionList(
992   ExceptionInfo *exception,const char *module,const char *function,
993   const size_t line,const ExceptionType severity,const char *tag,
994   const char *format,va_list operands)
995 {
996   char
997     message[MaxTextExtent],
998     path[MaxTextExtent],
999     reason[MaxTextExtent];
1000
1001   const char
1002     *locale,
1003     *type;
1004
1005   int
1006     n;
1007
1008   MagickBooleanType
1009     status;
1010
1011   size_t
1012     length;
1013
1014   assert(exception != (ExceptionInfo *) NULL);
1015   assert(exception->signature == MagickSignature);
1016   locale=GetLocaleExceptionMessage(severity,tag);
1017   (void) CopyMagickString(reason,locale,MaxTextExtent);
1018   (void) ConcatenateMagickString(reason," ",MaxTextExtent);
1019   length=strlen(reason);
1020 #if defined(MAGICKCORE_HAVE_VSNPRINTF)
1021   n=vsnprintf(reason+length,MaxTextExtent-length,format,operands);
1022 #else
1023   n=vsprintf(reason+length,format,operands);
1024 #endif
1025   if (n < 0)
1026     reason[MaxTextExtent-1]='\0';
1027   status=LogMagickEvent(ExceptionEvent,module,function,line,"%s",reason);
1028   GetPathComponent(module,TailPath,path);
1029   type="undefined";
1030   if ((severity >= WarningException) && (severity < ErrorException))
1031     type="warning";
1032   if ((severity >= ErrorException) && (severity < FatalErrorException))
1033     type="error";
1034   if (severity >= FatalErrorException)
1035     type="fatal";
1036   (void) FormatLocaleString(message,MaxTextExtent,"%s @ %s/%s/%s/%.20g",reason,
1037     type,path,function,(double) line);
1038   (void) ThrowException(exception,severity,message,(char *) NULL);
1039   return(status);
1040 }
1041
1042 MagickExport MagickBooleanType ThrowMagickException(ExceptionInfo *exception,
1043   const char *module,const char *function,const size_t line,
1044   const ExceptionType severity,const char *tag,const char *format,...)
1045 {
1046   MagickBooleanType
1047     status;
1048
1049   va_list
1050     operands;
1051
1052   va_start(operands,format);
1053   status=ThrowMagickExceptionList(exception,module,function,line,severity,tag,
1054     format,operands);
1055   va_end(operands);
1056   return(status);
1057 }