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