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