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