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