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