]> granicus.if.org Git - imagemagick/blob - MagickCore/exception.c
(no commit message)
[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 %                               John Cristy                                   %
17 %                                July 1993                                    %
18 %                                                                             %
19 %                                                                             %
20 %  Copyright 1999-2012 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   exception->relinquish=MagickTrue;
262   return(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
329 %      program.
330 %
331 %    o description: Specifies any description to the reason.
332 %
333 */
334 static void DefaultFatalErrorHandler(
335   const ExceptionType magick_unused(severity),
336   const char *reason,const char *description)
337 {
338   if (reason == (char *) NULL)
339     return;
340   (void) FormatLocaleFile(stderr,"%s: %s",GetClientName(),reason);
341   if (description != (char *) NULL)
342     (void) FormatLocaleFile(stderr," (%s)",description);
343   (void) FormatLocaleFile(stderr,".\n");
344   (void) fflush(stderr);
345   MagickCoreTerminus();
346   exit(1);
347 }
348 \f
349 /*
350 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
351 %                                                                             %
352 %                                                                             %
353 %                                                                             %
354 +   D e f a u l t W a r n i n g H a n d l e r                                 %
355 %                                                                             %
356 %                                                                             %
357 %                                                                             %
358 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
359 %
360 %  DefaultWarningHandler() displays a warning reason.
361 %
362 %  The format of the DefaultWarningHandler method is:
363 %
364 %      void DefaultWarningHandler(const ExceptionType severity,
365 %        const char *reason,const char *description)
366 %
367 %  A description of each parameter follows:
368 %
369 %    o severity: Specifies the numeric warning category.
370 %
371 %    o reason: Specifies the reason to display before terminating the
372 %      program.
373 %
374 %    o description: Specifies any description to the reason.
375 %
376 */
377 static void DefaultWarningHandler(const ExceptionType magick_unused(severity),
378   const char *reason,const char *description)
379 {
380   if (reason == (char *) NULL)
381     return;
382   (void) FormatLocaleFile(stderr,"%s: %s",GetClientName(),reason);
383   if (description != (char *) NULL)
384     (void) FormatLocaleFile(stderr," (%s)",description);
385   (void) FormatLocaleFile(stderr,".\n");
386   (void) fflush(stderr);
387 }
388 \f
389 /*
390 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
391 %                                                                             %
392 %                                                                             %
393 %                                                                             %
394 %   D e s t r o y E x c e p t i o n I n f o                                   %
395 %                                                                             %
396 %                                                                             %
397 %                                                                             %
398 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
399 %
400 %  DestroyExceptionInfo() deallocates memory associated with an exception.
401 %
402 %  The format of the DestroyExceptionInfo method is:
403 %
404 %      ExceptionInfo *DestroyExceptionInfo(ExceptionInfo *exception)
405 %
406 %  A description of each parameter follows:
407 %
408 %    o exception: the exception info.
409 %
410 */
411 MagickExport ExceptionInfo *DestroyExceptionInfo(ExceptionInfo *exception)
412 {
413   MagickBooleanType
414     relinquish;
415
416   assert(exception != (ExceptionInfo *) NULL);
417   assert(exception->signature == MagickSignature);
418   if (exception->semaphore == (SemaphoreInfo *) NULL)
419     AcquireSemaphoreInfo(&exception->semaphore);
420   LockSemaphoreInfo(exception->semaphore);
421   exception->severity=UndefinedException;
422   if (exception->exceptions != (void *) NULL)
423     exception->exceptions=(void *) DestroyLinkedList((LinkedListInfo *)
424       exception->exceptions,DestroyExceptionElement);
425   relinquish=exception->relinquish;
426   if (exception->relinquish != MagickFalse)
427     exception->signature=(~MagickSignature);
428   UnlockSemaphoreInfo(exception->semaphore);
429   DestroySemaphoreInfo(&exception->semaphore);
430   if (relinquish != MagickFalse)
431     exception=(ExceptionInfo *) RelinquishMagickMemory(exception);
432   return(exception);
433 }
434 \f
435 /*
436 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
437 %                                                                             %
438 %                                                                             %
439 %                                                                             %
440 %   G e t E x c e p t i o n I n f o                                           %
441 %                                                                             %
442 %                                                                             %
443 %                                                                             %
444 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
445 %
446 %  GetExceptionInfo() initializes an exception to default values.
447 %
448 %  The format of the GetExceptionInfo method is:
449 %
450 %      GetExceptionInfo(ExceptionInfo *exception)
451 %
452 %  A description of each parameter follows:
453 %
454 %    o exception: the exception info.
455 %
456 */
457 MagickExport void GetExceptionInfo(ExceptionInfo *exception)
458 {
459   assert(exception != (ExceptionInfo *) NULL);
460   (void) ResetMagickMemory(exception,0,sizeof(*exception));
461   exception->severity=UndefinedException;
462   exception->exceptions=(void *) NewLinkedList(0);
463   exception->semaphore=AllocateSemaphoreInfo();
464   exception->signature=MagickSignature;
465 }
466 \f
467 /*
468 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
469 %                                                                             %
470 %                                                                             %
471 %                                                                             %
472 %   G e t E x c e p t i o n M e s s a g e                                     %
473 %                                                                             %
474 %                                                                             %
475 %                                                                             %
476 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
477 %
478 %  GetExceptionMessage() returns the error message defined by the specified
479 %  error code.
480 %
481 %  The format of the GetExceptionMessage method is:
482 %
483 %      char *GetExceptionMessage(const int error)
484 %
485 %  A description of each parameter follows:
486 %
487 %    o error: the error code.
488 %
489 */
490 MagickExport char *GetExceptionMessage(const int error)
491 {
492   char
493     exception[MaxTextExtent];
494
495   *exception='\0';
496 #if defined(MAGICKCORE_HAVE_STRERROR_R)
497 #if !defined(MAGICKCORE_STRERROR_R_CHAR_P)
498   (void) strerror_r(error,exception,sizeof(exception));
499 #else
500   (void) CopyMagickString(exception,strerror_r(error,exception,
501     sizeof(exception)),sizeof(exception));
502 #endif
503 #else
504   (void) CopyMagickString(exception,strerror(error),sizeof(exception));
505 #endif
506   return(ConstantString(exception));
507 }
508 \f
509 /*
510 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
511 %                                                                             %
512 %                                                                             %
513 %                                                                             %
514 %   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                         %
515 %                                                                             %
516 %                                                                             %
517 %                                                                             %
518 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
519 %
520 %  GetLocaleExceptionMessage() converts a enumerated exception severity and tag
521 %  to a message in the current locale.
522 %
523 %  The format of the GetLocaleExceptionMessage method is:
524 %
525 %      const char *GetLocaleExceptionMessage(const ExceptionType severity,
526 %        const char *tag)
527 %
528 %  A description of each parameter follows:
529 %
530 %    o severity: the severity of the exception.
531 %
532 %    o tag: the message tag.
533 %
534 */
535
536 static const char *ExceptionSeverityToTag(const ExceptionType severity)
537 {
538   switch (severity)
539   {
540     case ResourceLimitWarning: return("Resource/Limit/Warning/");
541     case TypeWarning: return("Type/Warning/");
542     case OptionWarning: return("Option/Warning/");
543     case DelegateWarning: return("Delegate/Warning/");
544     case MissingDelegateWarning: return("Missing/Delegate/Warning/");
545     case CorruptImageWarning: return("Corrupt/Image/Warning/");
546     case FileOpenWarning: return("File/Open/Warning/");
547     case BlobWarning: return("Blob/Warning/");
548     case StreamWarning: return("Stream/Warning/");
549     case CacheWarning: return("Cache/Warning/");
550     case CoderWarning: return("Coder/Warning/");
551     case FilterWarning: return("Filter/Warning/");
552     case ModuleWarning: return("Module/Warning/");
553     case DrawWarning: return("Draw/Warning/");
554     case ImageWarning: return("Image/Warning/");
555     case WandWarning: return("Wand/Warning/");
556     case XServerWarning: return("XServer/Warning/");
557     case MonitorWarning: return("Monitor/Warning/");
558     case RegistryWarning: return("Registry/Warning/");
559     case ConfigureWarning: return("Configure/Warning/");
560     case PolicyWarning: return("Policy/Warning/");
561     case ResourceLimitError: return("Resource/Limit/Error/");
562     case TypeError: return("Type/Error/");
563     case OptionError: return("Option/Error/");
564     case DelegateError: return("Delegate/Error/");
565     case MissingDelegateError: return("Missing/Delegate/Error/");
566     case CorruptImageError: return("Corrupt/Image/Error/");
567     case FileOpenError: return("File/Open/Error/");
568     case BlobError: return("Blob/Error/");
569     case StreamError: return("Stream/Error/");
570     case CacheError: return("Cache/Error/");
571     case CoderError: return("Coder/Error/");
572     case FilterError: return("Filter/Error/");
573     case ModuleError: return("Module/Error/");
574     case DrawError: return("Draw/Error/");
575     case ImageError: return("Image/Error/");
576     case WandError: return("Wand/Error/");
577     case XServerError: return("XServer/Error/");
578     case MonitorError: return("Monitor/Error/");
579     case RegistryError: return("Registry/Error/");
580     case ConfigureError: return("Configure/Error/");
581     case PolicyError: return("Policy/Error/");
582     case ResourceLimitFatalError: return("Resource/Limit/FatalError/");
583     case TypeFatalError: return("Type/FatalError/");
584     case OptionFatalError: return("Option/FatalError/");
585     case DelegateFatalError: return("Delegate/FatalError/");
586     case MissingDelegateFatalError: return("Missing/Delegate/FatalError/");
587     case CorruptImageFatalError: return("Corrupt/Image/FatalError/");
588     case FileOpenFatalError: return("File/Open/FatalError/");
589     case BlobFatalError: return("Blob/FatalError/");
590     case StreamFatalError: return("Stream/FatalError/");
591     case CacheFatalError: return("Cache/FatalError/");
592     case CoderFatalError: return("Coder/FatalError/");
593     case FilterFatalError: return("Filter/FatalError/");
594     case ModuleFatalError: return("Module/FatalError/");
595     case DrawFatalError: return("Draw/FatalError/");
596     case ImageFatalError: return("Image/FatalError/");
597     case WandFatalError: return("Wand/FatalError/");
598     case XServerFatalError: return("XServer/FatalError/");
599     case MonitorFatalError: return("Monitor/FatalError/");
600     case RegistryFatalError: return("Registry/FatalError/");
601     case ConfigureFatalError: return("Configure/FatalError/");
602     case PolicyFatalError: return("Policy/FatalError/");
603     default: break;
604   }
605   return("");
606 }
607
608 MagickExport const char *GetLocaleExceptionMessage(const ExceptionType severity,
609   const char *tag)
610 {
611   char
612     message[MaxTextExtent];
613
614   const char
615     *locale_message;
616
617   assert(tag != (const char *) NULL);
618   (void) FormatLocaleString(message,MaxTextExtent,"Exception/%s%s",
619     ExceptionSeverityToTag(severity),tag);
620   locale_message=GetLocaleMessage(message);
621   if (locale_message == (const char *) NULL)
622     return(tag);
623   if (locale_message == message)
624     return(tag);
625   return(locale_message);
626 }
627 \f
628 /*
629 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
630 %                                                                             %
631 %                                                                             %
632 %                                                                             %
633 %   I n h e r i t E x c e p t i o n                                           %
634 %                                                                             %
635 %                                                                             %
636 %                                                                             %
637 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
638 %
639 %  InheritException() inherits an exception from a related exception.
640 %
641 %  The format of the InheritException method is:
642 %
643 %      InheritException(ExceptionInfo *exception,const ExceptionInfo *relative)
644 %
645 %  A description of each parameter follows:
646 %
647 %    o exception: the exception info.
648 %
649 %    o relative: the related exception info.
650 %
651 */
652 MagickExport void InheritException(ExceptionInfo *exception,
653   const ExceptionInfo *relative)
654 {
655   register const ExceptionInfo
656     *p;
657
658   assert(exception != (ExceptionInfo *) NULL);
659   assert(exception->signature == MagickSignature);
660   assert(relative != (ExceptionInfo *) NULL);
661   assert(relative->signature == MagickSignature);
662   if (relative->exceptions == (void *) NULL)
663     return;
664   LockSemaphoreInfo(exception->semaphore);
665   ResetLinkedListIterator((LinkedListInfo *) relative->exceptions);
666   p=(const ExceptionInfo *) GetNextValueInLinkedList((LinkedListInfo *)
667     relative->exceptions);
668   while (p != (const ExceptionInfo *) NULL)
669   {
670     (void) ThrowException(exception,p->severity,p->reason,p->description);
671     p=(const ExceptionInfo *) GetNextValueInLinkedList((LinkedListInfo *)
672       relative->exceptions);
673   }
674   UnlockSemaphoreInfo(exception->semaphore);
675 }
676 \f
677 /*
678 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
679 %                                                                             %
680 %                                                                             %
681 %                                                                             %
682 %   M a g i c k E r r o r                                                     %
683 %                                                                             %
684 %                                                                             %
685 %                                                                             %
686 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
687 %
688 %  MagickError() calls the exception handler methods with an error reason.
689 %
690 %  The format of the MagickError method is:
691 %
692 %      void MagickError(const ExceptionType error,const char *reason,
693 %        const char *description)
694 %
695 %  A description of each parameter follows:
696 %
697 %    o exception: Specifies the numeric error category.
698 %
699 %    o reason: Specifies the reason to display before terminating the
700 %      program.
701 %
702 %    o description: Specifies any description to the reason.
703 %
704 */
705 MagickExport void MagickError(const ExceptionType error,const char *reason,
706   const char *description)
707 {
708   if (error_handler != (ErrorHandler) NULL)
709     (*error_handler)(error,reason,description);
710 }
711 \f
712 /*
713 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
714 %                                                                             %
715 %                                                                             %
716 %                                                                             %
717 %   M a g i c k F a t al E r r o r                                            %
718 %                                                                             %
719 %                                                                             %
720 %                                                                             %
721 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
722 %
723 %  MagickFatalError() calls the fatal exception handler methods with an error
724 %  reason.
725 %
726 %  The format of the MagickError method is:
727 %
728 %      void MagickFatalError(const ExceptionType error,const char *reason,
729 %        const char *description)
730 %
731 %  A description of each parameter follows:
732 %
733 %    o exception: Specifies the numeric error category.
734 %
735 %    o reason: Specifies the reason to display before terminating the
736 %      program.
737 %
738 %    o description: Specifies any description to the reason.
739 %
740 */
741 MagickExport void MagickFatalError(const ExceptionType error,const char *reason,
742   const char *description)
743 {
744   if (fatal_error_handler != (ErrorHandler) NULL)
745     (*fatal_error_handler)(error,reason,description);
746 }
747 \f
748 /*
749 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
750 %                                                                             %
751 %                                                                             %
752 %                                                                             %
753 %   M a g i c k W a r n i n g                                                 %
754 %                                                                             %
755 %                                                                             %
756 %                                                                             %
757 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
758 %
759 %  MagickWarning() calls the warning handler methods with a warning reason.
760 %
761 %  The format of the MagickWarning method is:
762 %
763 %      void MagickWarning(const ExceptionType warning,const char *reason,
764 %        const char *description)
765 %
766 %  A description of each parameter follows:
767 %
768 %    o warning: the warning severity.
769 %
770 %    o reason: Define the reason for the warning.
771 %
772 %    o description: Describe the warning.
773 %
774 */
775 MagickExport void MagickWarning(const ExceptionType warning,const char *reason,
776   const char *description)
777 {
778   if (warning_handler != (WarningHandler) NULL)
779     (*warning_handler)(warning,reason,description);
780 }
781 \f
782 /*
783 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
784 %                                                                             %
785 %                                                                             %
786 %                                                                             %
787 %   S e t E r r o r H a n d l e r                                             %
788 %                                                                             %
789 %                                                                             %
790 %                                                                             %
791 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
792 %
793 %  SetErrorHandler() sets the exception handler to the specified method
794 %  and returns the previous exception handler.
795 %
796 %  The format of the SetErrorHandler method is:
797 %
798 %      ErrorHandler SetErrorHandler(ErrorHandler handler)
799 %
800 %  A description of each parameter follows:
801 %
802 %    o handler: the method to handle errors.
803 %
804 */
805 MagickExport ErrorHandler SetErrorHandler(ErrorHandler handler)
806 {
807   ErrorHandler
808     previous_handler;
809
810   previous_handler=error_handler;
811   error_handler=handler;
812   return(previous_handler);
813 }
814 \f
815 /*
816 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
817 %                                                                             %
818 %                                                                             %
819 %                                                                             %
820 %   S e t F a t a l E r r o r H a n d l e r                                   %
821 %                                                                             %
822 %                                                                             %
823 %                                                                             %
824 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
825 %
826 %  SetFatalErrorHandler() sets the fatal exception handler to the specified
827 %  method and returns the previous fatal exception handler.
828 %
829 %  The format of the SetErrorHandler method is:
830 %
831 %      ErrorHandler SetErrorHandler(ErrorHandler handler)
832 %
833 %  A description of each parameter follows:
834 %
835 %    o handler: the method to handle errors.
836 %
837 */
838 MagickExport FatalErrorHandler SetFatalErrorHandler(FatalErrorHandler handler)
839 {
840   FatalErrorHandler
841     previous_handler;
842
843   previous_handler=fatal_error_handler;
844   fatal_error_handler=handler;
845   return(previous_handler);
846 }
847 \f
848 /*
849 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
850 %                                                                             %
851 %                                                                             %
852 %                                                                             %
853 %   S e t W a r n i n g H a n d l e r                                         %
854 %                                                                             %
855 %                                                                             %
856 %                                                                             %
857 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
858 %
859 %  SetWarningHandler() sets the warning handler to the specified method
860 %  and returns the previous warning handler.
861 %
862 %  The format of the SetWarningHandler method is:
863 %
864 %      ErrorHandler SetWarningHandler(ErrorHandler handler)
865 %
866 %  A description of each parameter follows:
867 %
868 %    o handler: the method to handle warnings.
869 %
870 */
871 MagickExport WarningHandler SetWarningHandler(WarningHandler handler)
872 {
873   WarningHandler
874     previous_handler;
875
876   previous_handler=warning_handler;
877   warning_handler=handler;
878   return(previous_handler);
879 }
880 \f
881 /*
882 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
883 %                                                                             %
884 %                                                                             %
885 %                                                                             %
886 %   T h r o w E x c e p t i o n                                               %
887 %                                                                             %
888 %                                                                             %
889 %                                                                             %
890 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
891 %
892 %  ThrowException() throws an exception with the specified severity code,
893 %  reason, and optional description.
894 %
895 %  The format of the ThrowException method is:
896 %
897 %      MagickBooleanType ThrowException(ExceptionInfo *exception,
898 %        const ExceptionType severity,const char *reason,
899 %        const char *description)
900 %
901 %  A description of each parameter follows:
902 %
903 %    o exception: the exception info.
904 %
905 %    o severity: the severity of the exception.
906 %
907 %    o reason: the reason for the exception.
908 %
909 %    o description: the exception description.
910 %
911 */
912 MagickExport MagickBooleanType ThrowException(ExceptionInfo *exception,
913   const ExceptionType severity,const char *reason,const char *description)
914 {
915   register ExceptionInfo
916     *p;
917
918   assert(exception != (ExceptionInfo *) NULL);
919   assert(exception->signature == MagickSignature);
920   p=(ExceptionInfo *) GetLastValueInLinkedList((LinkedListInfo *)
921     exception->exceptions);
922   if ((p != (ExceptionInfo *) NULL) && (p->severity == severity) &&
923       (LocaleCompare(exception->reason,reason) == 0) &&
924       (LocaleCompare(exception->description,description) == 0))
925     return(MagickTrue);
926   p=(ExceptionInfo *) AcquireMagickMemory(sizeof(*p));
927   if (p == (ExceptionInfo *) NULL)
928     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
929   (void) ResetMagickMemory(p,0,sizeof(*p));
930   p->severity=severity;
931   if (reason != (const char *) NULL)
932     p->reason=ConstantString(reason);
933   if (description != (const char *) NULL)
934     p->description=ConstantString(description);
935   p->signature=MagickSignature;
936   (void) AppendValueToLinkedList((LinkedListInfo *) exception->exceptions,p);
937   exception->severity=p->severity;
938   exception->reason=p->reason;
939   exception->description=p->description;
940   return(MagickTrue);
941 }
942 \f
943 /*
944 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
945 %                                                                             %
946 %                                                                             %
947 %                                                                             %
948 %   T h r o w M a g i c k E x c e p t i o n                                   %
949 %                                                                             %
950 %                                                                             %
951 %                                                                             %
952 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
953 %
954 %  ThrowMagickException logs an exception as determined by the log
955 %  configuration file.  If an error occurs, MagickFalse is returned
956 %  otherwise MagickTrue.
957 %
958 %  The format of the ThrowMagickException method is:
959 %
960 %      MagickBooleanType ThrowFileException(ExceptionInfo *exception,
961 %        const char *module,const char *function,const size_t line,
962 %        const ExceptionType severity,const char *tag,const char *format,...)
963 %
964 %  A description of each parameter follows:
965 %
966 %    o exception: the exception info.
967 %
968 %    o filename: the source module filename.
969 %
970 %    o function: the function name.
971 %
972 %    o line: the line number of the source module.
973 %
974 %    o severity: Specifies the numeric error category.
975 %
976 %    o tag: the locale tag.
977 %
978 %    o format: the output format.
979 %
980 */
981
982 MagickExport MagickBooleanType ThrowMagickExceptionList(ExceptionInfo *exception,
983   const char *module,const char *function,const size_t line,
984   const ExceptionType severity,const char *tag,const char *format,
985   va_list operands)
986 {
987   char
988     message[MaxTextExtent],
989     path[MaxTextExtent],
990     reason[MaxTextExtent];
991
992   const char
993     *locale,
994     *type;
995
996   int
997     n;
998
999   MagickBooleanType
1000     status;
1001
1002   size_t
1003     length;
1004
1005   assert(exception != (ExceptionInfo *) NULL);
1006   assert(exception->signature == MagickSignature);
1007   locale=GetLocaleExceptionMessage(severity,tag);
1008   (void) CopyMagickString(reason,locale,MaxTextExtent);
1009   (void) ConcatenateMagickString(reason," ",MaxTextExtent);
1010   length=strlen(reason);
1011 #if defined(MAGICKCORE_HAVE_VSNPRINTF)
1012   n=vsnprintf(reason+length,MaxTextExtent-length,format,operands);
1013 #else
1014   n=vsprintf(reason+length,format,operands);
1015 #endif
1016   if (n < 0)
1017     reason[MaxTextExtent-1]='\0';
1018   status=LogMagickEvent(ExceptionEvent,module,function,line,"%s",reason);
1019   GetPathComponent(module,TailPath,path);
1020   type="undefined";
1021   if ((severity >= WarningException) && (severity < ErrorException))
1022     type="warning";
1023   if ((severity >= ErrorException) && (severity < FatalErrorException))
1024     type="error";
1025   if (severity >= FatalErrorException)
1026     type="fatal";
1027   (void) FormatLocaleString(message,MaxTextExtent,"%s @ %s/%s/%s/%.20g",reason,
1028     type,path,function,(double) line);
1029   (void) ThrowException(exception,severity,message,(char *) NULL);
1030   return(status);
1031 }
1032
1033 MagickExport MagickBooleanType ThrowMagickException(ExceptionInfo *exception,
1034   const char *module,const char *function,const size_t line,
1035   const ExceptionType severity,const char *tag,const char *format,...)
1036 {
1037   MagickBooleanType
1038     status;
1039
1040   va_list
1041     operands;
1042
1043   va_start(operands,format);
1044   status=ThrowMagickExceptionList(exception,module,function,line,severity,tag,
1045     format,operands);
1046   va_end(operands);
1047   return(status);
1048 }