blob: f034d26320dd9d247d9fe407c25ed0449296cd35 [file] [log] [blame]
cristy3ed852e2009-09-05 21:47:34 +00001/*
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 %
cristyde984cd2013-12-01 14:49:27 +000016% Cristy %
cristy3ed852e2009-09-05 21:47:34 +000017% July 1993 %
18% %
19% %
cristyfe676ee2013-11-18 13:03:38 +000020% Copyright 1999-2014 ImageMagick Studio LLC, a non-profit organization %
cristy3ed852e2009-09-05 21:47:34 +000021% 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
40/*
41 Include declarations.
42*/
cristy4c08aed2011-07-01 19:47:50 +000043#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"
cristyd1dd6e42011-09-04 01:46:08 +000054#include "MagickCore/utility-private.h"
cristy3ed852e2009-09-05 21:47:34 +000055
56/*
57 Forward declarations.
58*/
59#if defined(__cplusplus) || defined(c_plusplus)
60extern "C" {
61#endif
62
63static 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
72/*
73 Global declarations.
74*/
75static ErrorHandler
76 error_handler = DefaultErrorHandler;
77
78static FatalErrorHandler
79 fatal_error_handler = DefaultFatalErrorHandler;
80
81static WarningHandler
82 warning_handler = DefaultWarningHandler;
83
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*/
102MagickExport ExceptionInfo *AcquireExceptionInfo(void)
103{
104 ExceptionInfo
105 *exception;
106
cristy73bd4a52010-10-05 11:24:23 +0000107 exception=(ExceptionInfo *) AcquireMagickMemory(sizeof(*exception));
cristy3ed852e2009-09-05 21:47:34 +0000108 if (exception == (ExceptionInfo *) NULL)
109 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
110 GetExceptionInfo(exception);
111 exception->relinquish=MagickTrue;
112 return(exception);
113}
114
115/*
116%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
117% %
118% %
119% %
120% C l e a r M a g i c k E x c e p t i o n %
121% %
122% %
123% %
124%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
125%
126% ClearMagickException() clears any exception that may not have been caught
127% yet.
128%
129% The format of the ClearMagickException method is:
130%
131% ClearMagickException(ExceptionInfo *exception)
132%
133% A description of each parameter follows:
134%
135% o exception: the exception info.
136%
137*/
138
139static 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
153MagickExport void ClearMagickException(ExceptionInfo *exception)
154{
155 register ExceptionInfo
156 *p;
157
158 assert(exception != (ExceptionInfo *) NULL);
159 assert(exception->signature == MagickSignature);
160 if (exception->exceptions == (void *) NULL)
161 return;
cristyf84a1932010-01-03 18:00:18 +0000162 LockSemaphoreInfo(exception->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000163 p=(ExceptionInfo *) RemoveLastElementFromLinkedList((LinkedListInfo *)
164 exception->exceptions);
165 while (p != (ExceptionInfo *) NULL)
166 {
167 (void) DestroyExceptionElement(p);
168 p=(ExceptionInfo *) RemoveLastElementFromLinkedList((LinkedListInfo *)
169 exception->exceptions);
170 }
171 exception->severity=UndefinedException;
172 exception->reason=(char *) NULL;
173 exception->description=(char *) NULL;
cristyf84a1932010-01-03 18:00:18 +0000174 UnlockSemaphoreInfo(exception->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000175 errno=0;
176}
177
178/*
179%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
180% %
181% %
182% %
183% C a t c h E x c e p t i o n %
184% %
185% %
186% %
187%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
188%
189% CatchException() returns if no exceptions is found otherwise it reports
190% the exception as a warning, error, or fatal depending on the severity.
191%
192% The format of the CatchException method is:
193%
194% CatchException(ExceptionInfo *exception)
195%
196% A description of each parameter follows:
197%
198% o exception: the exception info.
199%
200*/
201MagickExport void CatchException(ExceptionInfo *exception)
202{
203 register const ExceptionInfo
204 *p;
205
206 assert(exception != (ExceptionInfo *) NULL);
207 assert(exception->signature == MagickSignature);
208 if (exception->exceptions == (void *) NULL)
209 return;
cristyf84a1932010-01-03 18:00:18 +0000210 LockSemaphoreInfo(exception->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000211 ResetLinkedListIterator((LinkedListInfo *) exception->exceptions);
212 p=(const ExceptionInfo *) GetNextValueInLinkedList((LinkedListInfo *)
213 exception->exceptions);
214 while (p != (const ExceptionInfo *) NULL)
215 {
216 if ((p->severity >= WarningException) && (p->severity < ErrorException))
217 MagickWarning(p->severity,p->reason,p->description);
218 if ((p->severity >= ErrorException) && (p->severity < FatalErrorException))
219 MagickError(p->severity,p->reason,p->description);
cristy32cca402010-01-23 04:02:23 +0000220 if (p->severity >= FatalErrorException)
cristy3ed852e2009-09-05 21:47:34 +0000221 MagickFatalError(p->severity,p->reason,p->description);
222 p=(const ExceptionInfo *) GetNextValueInLinkedList((LinkedListInfo *)
223 exception->exceptions);
224 }
cristyf84a1932010-01-03 18:00:18 +0000225 UnlockSemaphoreInfo(exception->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000226 ClearMagickException(exception);
227}
228
229/*
230%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
231% %
232% %
233% %
cristyc82a27b2011-10-21 01:07:16 +0000234% C l o n e E x c e p t i o n I n f o %
235% %
236% %
237% %
238%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
239%
240% CloneExceptionInfo() clones the ExceptionInfo structure.
241%
242% The format of the CloneExceptionInfo method is:
243%
244% ExceptionInfo *CloneException(ExceptionInfo *exception)
245%
246% A description of each parameter follows:
247%
248% o exception: the exception info.
249%
250*/
251MagickExport ExceptionInfo *CloneExceptionInfo(ExceptionInfo *exception)
252{
253 ExceptionInfo
254 *clone_exception;
255
256 clone_exception=(ExceptionInfo *) AcquireMagickMemory(sizeof(*exception));
257 if (clone_exception == (ExceptionInfo *) NULL)
258 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
259 GetExceptionInfo(clone_exception);
260 InheritException(clone_exception,exception);
cristy4592b2c2014-01-12 14:12:01 +0000261 clone_exception->relinquish=MagickTrue;
cristya0dfced2014-01-12 15:22:46 +0000262 return(clone_exception);
cristyc82a27b2011-10-21 01:07:16 +0000263}
264
265/*
266%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
267% %
268% %
269% %
cristy3ed852e2009-09-05 21:47:34 +0000270+ D e f a u l t E r r o r H a n d l e r %
271% %
272% %
273% %
274%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
275%
276% DefaultErrorHandler() displays an error reason.
277%
278% The format of the DefaultErrorHandler method is:
279%
280% void MagickError(const ExceptionType severity,const char *reason,
281% const char *description)
282%
283% A description of each parameter follows:
284%
285% o severity: Specifies the numeric error category.
286%
287% o reason: Specifies the reason to display before terminating the
288% program.
289%
290% o description: Specifies any description to the reason.
291%
292*/
293static void DefaultErrorHandler(const ExceptionType magick_unused(severity),
294 const char *reason,const char *description)
295{
296 if (reason == (char *) NULL)
297 return;
cristyb51dff52011-05-19 16:55:47 +0000298 (void) FormatLocaleFile(stderr,"%s: %s",GetClientName(),reason);
cristy3ed852e2009-09-05 21:47:34 +0000299 if (description != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +0000300 (void) FormatLocaleFile(stderr," (%s)",description);
301 (void) FormatLocaleFile(stderr,".\n");
cristy3ed852e2009-09-05 21:47:34 +0000302 (void) fflush(stderr);
303}
304
305/*
306%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
307% %
308% %
309% %
310+ D e f a u l t F a t a l E r r o r H a n d l e r %
311% %
312% %
313% %
314%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
315%
316% DefaultFatalErrorHandler() displays an error reason and then terminates the
317% program.
318%
319% The format of the DefaultFatalErrorHandler method is:
320%
321% void MagickFatalError(const ExceptionType severity,const char *reason,
322% const char *description)
323%
324% A description of each parameter follows:
325%
326% o severity: Specifies the numeric error category.
327%
cristyb200b6c2012-12-13 15:20:26 +0000328% o reason: Specifies the reason to display before terminating the program.
cristy3ed852e2009-09-05 21:47:34 +0000329%
330% o description: Specifies any description to the reason.
331%
332*/
cristyb200b6c2012-12-13 15:20:26 +0000333static void DefaultFatalErrorHandler(const ExceptionType severity,
cristy3ed852e2009-09-05 21:47:34 +0000334 const char *reason,const char *description)
335{
336 if (reason == (char *) NULL)
337 return;
cristyb51dff52011-05-19 16:55:47 +0000338 (void) FormatLocaleFile(stderr,"%s: %s",GetClientName(),reason);
cristy3ed852e2009-09-05 21:47:34 +0000339 if (description != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +0000340 (void) FormatLocaleFile(stderr," (%s)",description);
341 (void) FormatLocaleFile(stderr,".\n");
cristy3ed852e2009-09-05 21:47:34 +0000342 (void) fflush(stderr);
343 MagickCoreTerminus();
cristyb4d552c2012-12-13 15:42:17 +0000344 exit((int) (severity-FatalErrorException)+1);
cristy3ed852e2009-09-05 21:47:34 +0000345}
346
347/*
348%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
349% %
350% %
351% %
352+ D e f a u l t W a r n i n g H a n d l e r %
353% %
354% %
355% %
356%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
357%
358% DefaultWarningHandler() displays a warning reason.
359%
360% The format of the DefaultWarningHandler method is:
361%
cristy3b743bb2009-09-14 16:07:59 +0000362% void DefaultWarningHandler(const ExceptionType severity,
cristy3ed852e2009-09-05 21:47:34 +0000363% const char *reason,const char *description)
364%
365% A description of each parameter follows:
366%
cristy3b743bb2009-09-14 16:07:59 +0000367% o severity: Specifies the numeric warning category.
cristy3ed852e2009-09-05 21:47:34 +0000368%
369% o reason: Specifies the reason to display before terminating the
370% program.
371%
372% o description: Specifies any description to the reason.
373%
374*/
375static void DefaultWarningHandler(const ExceptionType magick_unused(severity),
376 const char *reason,const char *description)
377{
378 if (reason == (char *) NULL)
379 return;
cristyb51dff52011-05-19 16:55:47 +0000380 (void) FormatLocaleFile(stderr,"%s: %s",GetClientName(),reason);
cristy3ed852e2009-09-05 21:47:34 +0000381 if (description != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +0000382 (void) FormatLocaleFile(stderr," (%s)",description);
383 (void) FormatLocaleFile(stderr,".\n");
cristy3ed852e2009-09-05 21:47:34 +0000384 (void) fflush(stderr);
385}
386
387/*
388%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
389% %
390% %
391% %
392% D e s t r o y E x c e p t i o n I n f o %
393% %
394% %
395% %
396%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
397%
398% DestroyExceptionInfo() deallocates memory associated with an exception.
399%
400% The format of the DestroyExceptionInfo method is:
401%
402% ExceptionInfo *DestroyExceptionInfo(ExceptionInfo *exception)
403%
404% A description of each parameter follows:
405%
406% o exception: the exception info.
407%
408*/
409MagickExport ExceptionInfo *DestroyExceptionInfo(ExceptionInfo *exception)
410{
411 MagickBooleanType
412 relinquish;
413
414 assert(exception != (ExceptionInfo *) NULL);
415 assert(exception->signature == MagickSignature);
cristy78883b22010-01-11 16:38:53 +0000416 if (exception->semaphore == (SemaphoreInfo *) NULL)
417 AcquireSemaphoreInfo(&exception->semaphore);
cristyf84a1932010-01-03 18:00:18 +0000418 LockSemaphoreInfo(exception->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000419 exception->severity=UndefinedException;
420 if (exception->exceptions != (void *) NULL)
421 exception->exceptions=(void *) DestroyLinkedList((LinkedListInfo *)
422 exception->exceptions,DestroyExceptionElement);
423 relinquish=exception->relinquish;
424 if (exception->relinquish != MagickFalse)
425 exception->signature=(~MagickSignature);
cristyf84a1932010-01-03 18:00:18 +0000426 UnlockSemaphoreInfo(exception->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000427 DestroySemaphoreInfo(&exception->semaphore);
428 if (relinquish != MagickFalse)
429 exception=(ExceptionInfo *) RelinquishMagickMemory(exception);
430 return(exception);
431}
432
433/*
434%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
435% %
436% %
437% %
438% G e t E x c e p t i o n I n f o %
439% %
440% %
441% %
442%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
443%
444% GetExceptionInfo() initializes an exception to default values.
445%
446% The format of the GetExceptionInfo method is:
447%
448% GetExceptionInfo(ExceptionInfo *exception)
449%
450% A description of each parameter follows:
451%
452% o exception: the exception info.
453%
454*/
455MagickExport void GetExceptionInfo(ExceptionInfo *exception)
456{
457 assert(exception != (ExceptionInfo *) NULL);
458 (void) ResetMagickMemory(exception,0,sizeof(*exception));
459 exception->severity=UndefinedException;
460 exception->exceptions=(void *) NewLinkedList(0);
cristy18b17442009-10-25 18:36:48 +0000461 exception->semaphore=AllocateSemaphoreInfo();
cristy3ed852e2009-09-05 21:47:34 +0000462 exception->signature=MagickSignature;
463}
464
465/*
466%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
467% %
468% %
469% %
470% G e t E x c e p t i o n M e s s a g e %
471% %
472% %
473% %
474%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
475%
476% GetExceptionMessage() returns the error message defined by the specified
477% error code.
478%
479% The format of the GetExceptionMessage method is:
480%
481% char *GetExceptionMessage(const int error)
482%
483% A description of each parameter follows:
484%
485% o error: the error code.
486%
487*/
488MagickExport char *GetExceptionMessage(const int error)
489{
490 char
491 exception[MaxTextExtent];
492
cristyb5641692010-04-08 22:49:59 +0000493 *exception='\0';
cristy3ed852e2009-09-05 21:47:34 +0000494#if defined(MAGICKCORE_HAVE_STRERROR_R)
cristy7d4a1d62011-10-13 15:54:12 +0000495#if !defined(MAGICKCORE_STRERROR_R_CHAR_P)
cristy3ed852e2009-09-05 21:47:34 +0000496 (void) strerror_r(error,exception,sizeof(exception));
497#else
cristy866a02f2011-09-07 12:10:32 +0000498 (void) CopyMagickString(exception,strerror_r(error,exception,
499 sizeof(exception)),sizeof(exception));
500#endif
501#else
cristy3ed852e2009-09-05 21:47:34 +0000502 (void) CopyMagickString(exception,strerror(error),sizeof(exception));
503#endif
504 return(ConstantString(exception));
505}
506
507/*
508%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
509% %
510% %
511% %
512% 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 %
513% %
514% %
515% %
516%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
517%
518% GetLocaleExceptionMessage() converts a enumerated exception severity and tag
519% to a message in the current locale.
520%
521% The format of the GetLocaleExceptionMessage method is:
522%
523% const char *GetLocaleExceptionMessage(const ExceptionType severity,
524% const char *tag)
525%
526% A description of each parameter follows:
527%
528% o severity: the severity of the exception.
529%
530% o tag: the message tag.
531%
532*/
533
534static const char *ExceptionSeverityToTag(const ExceptionType severity)
535{
536 switch (severity)
537 {
538 case ResourceLimitWarning: return("Resource/Limit/Warning/");
539 case TypeWarning: return("Type/Warning/");
540 case OptionWarning: return("Option/Warning/");
541 case DelegateWarning: return("Delegate/Warning/");
542 case MissingDelegateWarning: return("Missing/Delegate/Warning/");
543 case CorruptImageWarning: return("Corrupt/Image/Warning/");
544 case FileOpenWarning: return("File/Open/Warning/");
545 case BlobWarning: return("Blob/Warning/");
546 case StreamWarning: return("Stream/Warning/");
547 case CacheWarning: return("Cache/Warning/");
548 case CoderWarning: return("Coder/Warning/");
cristy992729d2010-01-01 15:45:06 +0000549 case FilterWarning: return("Filter/Warning/");
cristy3ed852e2009-09-05 21:47:34 +0000550 case ModuleWarning: return("Module/Warning/");
551 case DrawWarning: return("Draw/Warning/");
552 case ImageWarning: return("Image/Warning/");
553 case WandWarning: return("Wand/Warning/");
554 case XServerWarning: return("XServer/Warning/");
555 case MonitorWarning: return("Monitor/Warning/");
556 case RegistryWarning: return("Registry/Warning/");
557 case ConfigureWarning: return("Configure/Warning/");
558 case PolicyWarning: return("Policy/Warning/");
559 case ResourceLimitError: return("Resource/Limit/Error/");
560 case TypeError: return("Type/Error/");
561 case OptionError: return("Option/Error/");
562 case DelegateError: return("Delegate/Error/");
563 case MissingDelegateError: return("Missing/Delegate/Error/");
564 case CorruptImageError: return("Corrupt/Image/Error/");
565 case FileOpenError: return("File/Open/Error/");
566 case BlobError: return("Blob/Error/");
567 case StreamError: return("Stream/Error/");
568 case CacheError: return("Cache/Error/");
569 case CoderError: return("Coder/Error/");
cristy992729d2010-01-01 15:45:06 +0000570 case FilterError: return("Filter/Error/");
cristy3ed852e2009-09-05 21:47:34 +0000571 case ModuleError: return("Module/Error/");
572 case DrawError: return("Draw/Error/");
573 case ImageError: return("Image/Error/");
574 case WandError: return("Wand/Error/");
575 case XServerError: return("XServer/Error/");
576 case MonitorError: return("Monitor/Error/");
577 case RegistryError: return("Registry/Error/");
578 case ConfigureError: return("Configure/Error/");
579 case PolicyError: return("Policy/Error/");
580 case ResourceLimitFatalError: return("Resource/Limit/FatalError/");
581 case TypeFatalError: return("Type/FatalError/");
582 case OptionFatalError: return("Option/FatalError/");
583 case DelegateFatalError: return("Delegate/FatalError/");
584 case MissingDelegateFatalError: return("Missing/Delegate/FatalError/");
585 case CorruptImageFatalError: return("Corrupt/Image/FatalError/");
586 case FileOpenFatalError: return("File/Open/FatalError/");
587 case BlobFatalError: return("Blob/FatalError/");
588 case StreamFatalError: return("Stream/FatalError/");
589 case CacheFatalError: return("Cache/FatalError/");
590 case CoderFatalError: return("Coder/FatalError/");
cristy992729d2010-01-01 15:45:06 +0000591 case FilterFatalError: return("Filter/FatalError/");
cristy3ed852e2009-09-05 21:47:34 +0000592 case ModuleFatalError: return("Module/FatalError/");
593 case DrawFatalError: return("Draw/FatalError/");
594 case ImageFatalError: return("Image/FatalError/");
595 case WandFatalError: return("Wand/FatalError/");
596 case XServerFatalError: return("XServer/FatalError/");
597 case MonitorFatalError: return("Monitor/FatalError/");
598 case RegistryFatalError: return("Registry/FatalError/");
599 case ConfigureFatalError: return("Configure/FatalError/");
600 case PolicyFatalError: return("Policy/FatalError/");
601 default: break;
602 }
603 return("");
604}
605
606MagickExport const char *GetLocaleExceptionMessage(const ExceptionType severity,
607 const char *tag)
608{
609 char
610 message[MaxTextExtent];
611
612 const char
613 *locale_message;
614
615 assert(tag != (const char *) NULL);
cristyb51dff52011-05-19 16:55:47 +0000616 (void) FormatLocaleString(message,MaxTextExtent,"Exception/%s%s",
cristy3ed852e2009-09-05 21:47:34 +0000617 ExceptionSeverityToTag(severity),tag);
618 locale_message=GetLocaleMessage(message);
619 if (locale_message == (const char *) NULL)
620 return(tag);
621 if (locale_message == message)
622 return(tag);
623 return(locale_message);
624}
625
626/*
627%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
628% %
629% %
630% %
631% I n h e r i t E x c e p t i o n %
632% %
633% %
634% %
635%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
636%
637% InheritException() inherits an exception from a related exception.
638%
639% The format of the InheritException method is:
640%
641% InheritException(ExceptionInfo *exception,const ExceptionInfo *relative)
642%
643% A description of each parameter follows:
644%
645% o exception: the exception info.
646%
647% o relative: the related exception info.
648%
649*/
650MagickExport void InheritException(ExceptionInfo *exception,
651 const ExceptionInfo *relative)
652{
653 register const ExceptionInfo
654 *p;
655
656 assert(exception != (ExceptionInfo *) NULL);
657 assert(exception->signature == MagickSignature);
658 assert(relative != (ExceptionInfo *) NULL);
659 assert(relative->signature == MagickSignature);
660 if (relative->exceptions == (void *) NULL)
661 return;
cristy93670402013-02-19 12:42:11 +0000662 LockSemaphoreInfo(relative->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000663 ResetLinkedListIterator((LinkedListInfo *) relative->exceptions);
664 p=(const ExceptionInfo *) GetNextValueInLinkedList((LinkedListInfo *)
665 relative->exceptions);
666 while (p != (const ExceptionInfo *) NULL)
667 {
668 (void) ThrowException(exception,p->severity,p->reason,p->description);
669 p=(const ExceptionInfo *) GetNextValueInLinkedList((LinkedListInfo *)
670 relative->exceptions);
671 }
cristy93670402013-02-19 12:42:11 +0000672 UnlockSemaphoreInfo(relative->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000673}
674
675/*
676%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
677% %
678% %
679% %
680% M a g i c k E r r o r %
681% %
682% %
683% %
684%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
685%
686% MagickError() calls the exception handler methods with an error reason.
687%
688% The format of the MagickError method is:
689%
690% void MagickError(const ExceptionType error,const char *reason,
691% const char *description)
692%
693% A description of each parameter follows:
694%
695% o exception: Specifies the numeric error category.
696%
697% o reason: Specifies the reason to display before terminating the
698% program.
699%
700% o description: Specifies any description to the reason.
701%
702*/
703MagickExport void MagickError(const ExceptionType error,const char *reason,
704 const char *description)
705{
706 if (error_handler != (ErrorHandler) NULL)
707 (*error_handler)(error,reason,description);
708}
709
710/*
711%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
712% %
713% %
714% %
715% M a g i c k F a t al E r r o r %
716% %
717% %
718% %
719%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
720%
721% MagickFatalError() calls the fatal exception handler methods with an error
722% reason.
723%
724% The format of the MagickError method is:
725%
726% void MagickFatalError(const ExceptionType error,const char *reason,
727% const char *description)
728%
729% A description of each parameter follows:
730%
731% o exception: Specifies the numeric error category.
732%
733% o reason: Specifies the reason to display before terminating the
734% program.
735%
736% o description: Specifies any description to the reason.
737%
738*/
739MagickExport void MagickFatalError(const ExceptionType error,const char *reason,
740 const char *description)
741{
742 if (fatal_error_handler != (ErrorHandler) NULL)
743 (*fatal_error_handler)(error,reason,description);
744}
745
746/*
747%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
748% %
749% %
750% %
751% M a g i c k W a r n i n g %
752% %
753% %
754% %
755%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
756%
757% MagickWarning() calls the warning handler methods with a warning reason.
758%
759% The format of the MagickWarning method is:
760%
761% void MagickWarning(const ExceptionType warning,const char *reason,
762% const char *description)
763%
764% A description of each parameter follows:
765%
766% o warning: the warning severity.
767%
768% o reason: Define the reason for the warning.
769%
770% o description: Describe the warning.
771%
772*/
773MagickExport void MagickWarning(const ExceptionType warning,const char *reason,
774 const char *description)
775{
776 if (warning_handler != (WarningHandler) NULL)
777 (*warning_handler)(warning,reason,description);
778}
779
780/*
781%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
782% %
783% %
784% %
785% S e t E r r o r H a n d l e r %
786% %
787% %
788% %
789%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
790%
791% SetErrorHandler() sets the exception handler to the specified method
792% and returns the previous exception handler.
793%
794% The format of the SetErrorHandler method is:
795%
796% ErrorHandler SetErrorHandler(ErrorHandler handler)
797%
798% A description of each parameter follows:
799%
800% o handler: the method to handle errors.
801%
802*/
803MagickExport ErrorHandler SetErrorHandler(ErrorHandler handler)
804{
805 ErrorHandler
806 previous_handler;
807
808 previous_handler=error_handler;
809 error_handler=handler;
810 return(previous_handler);
811}
812
813/*
814%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
815% %
816% %
817% %
818% S e t F a t a l E r r o r H a n d l e r %
819% %
820% %
821% %
822%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
823%
824% SetFatalErrorHandler() sets the fatal exception handler to the specified
825% method and returns the previous fatal exception handler.
826%
827% The format of the SetErrorHandler method is:
828%
829% ErrorHandler SetErrorHandler(ErrorHandler handler)
830%
831% A description of each parameter follows:
832%
833% o handler: the method to handle errors.
834%
835*/
836MagickExport FatalErrorHandler SetFatalErrorHandler(FatalErrorHandler handler)
837{
838 FatalErrorHandler
839 previous_handler;
840
841 previous_handler=fatal_error_handler;
842 fatal_error_handler=handler;
843 return(previous_handler);
844}
845
846/*
847%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
848% %
849% %
850% %
851% S e t W a r n i n g H a n d l e r %
852% %
853% %
854% %
855%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
856%
857% SetWarningHandler() sets the warning handler to the specified method
858% and returns the previous warning handler.
859%
860% The format of the SetWarningHandler method is:
861%
862% ErrorHandler SetWarningHandler(ErrorHandler handler)
863%
864% A description of each parameter follows:
865%
866% o handler: the method to handle warnings.
867%
868*/
869MagickExport WarningHandler SetWarningHandler(WarningHandler handler)
870{
871 WarningHandler
872 previous_handler;
873
874 previous_handler=warning_handler;
875 warning_handler=handler;
876 return(previous_handler);
877}
878
879/*
880%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
881% %
882% %
883% %
884% T h r o w E x c e p t i o n %
885% %
886% %
887% %
888%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
889%
890% ThrowException() throws an exception with the specified severity code,
891% reason, and optional description.
892%
893% The format of the ThrowException method is:
894%
895% MagickBooleanType ThrowException(ExceptionInfo *exception,
896% const ExceptionType severity,const char *reason,
897% const char *description)
898%
899% A description of each parameter follows:
900%
901% o exception: the exception info.
902%
903% o severity: the severity of the exception.
904%
905% o reason: the reason for the exception.
906%
907% o description: the exception description.
908%
909*/
910MagickExport MagickBooleanType ThrowException(ExceptionInfo *exception,
911 const ExceptionType severity,const char *reason,const char *description)
912{
913 register ExceptionInfo
914 *p;
915
916 assert(exception != (ExceptionInfo *) NULL);
917 assert(exception->signature == MagickSignature);
cristy93670402013-02-19 12:42:11 +0000918 LockSemaphoreInfo(exception->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000919 p=(ExceptionInfo *) GetLastValueInLinkedList((LinkedListInfo *)
920 exception->exceptions);
921 if ((p != (ExceptionInfo *) NULL) && (p->severity == severity) &&
922 (LocaleCompare(exception->reason,reason) == 0) &&
923 (LocaleCompare(exception->description,description) == 0))
cristy93670402013-02-19 12:42:11 +0000924 {
925 UnlockSemaphoreInfo(exception->semaphore);
926 return(MagickTrue);
927 }
cristy73bd4a52010-10-05 11:24:23 +0000928 p=(ExceptionInfo *) AcquireMagickMemory(sizeof(*p));
cristy3ed852e2009-09-05 21:47:34 +0000929 if (p == (ExceptionInfo *) NULL)
cristy93670402013-02-19 12:42:11 +0000930 {
931 UnlockSemaphoreInfo(exception->semaphore);
932 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
933 }
cristy3ed852e2009-09-05 21:47:34 +0000934 (void) ResetMagickMemory(p,0,sizeof(*p));
935 p->severity=severity;
936 if (reason != (const char *) NULL)
937 p->reason=ConstantString(reason);
938 if (description != (const char *) NULL)
939 p->description=ConstantString(description);
940 p->signature=MagickSignature;
941 (void) AppendValueToLinkedList((LinkedListInfo *) exception->exceptions,p);
cristy992f5372013-05-15 12:20:19 +0000942 if (p->severity >= exception->severity)
943 {
944 exception->severity=p->severity;
945 exception->reason=p->reason;
946 exception->description=p->description;
947 }
cristy93670402013-02-19 12:42:11 +0000948 UnlockSemaphoreInfo(exception->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000949 return(MagickTrue);
950}
951
952/*
953%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
954% %
955% %
956% %
957% T h r o w M a g i c k E x c e p t i o n %
958% %
959% %
960% %
961%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
962%
anthony5216f822012-04-10 13:02:37 +0000963% ThrowMagickException logs an exception as determined by the log
964% configuration file. If an error occurs, MagickFalse is returned
965% otherwise MagickTrue.
cristy3ed852e2009-09-05 21:47:34 +0000966%
967% The format of the ThrowMagickException method is:
968%
969% MagickBooleanType ThrowFileException(ExceptionInfo *exception,
cristybb503372010-05-27 20:51:26 +0000970% const char *module,const char *function,const size_t line,
cristy3ed852e2009-09-05 21:47:34 +0000971% const ExceptionType severity,const char *tag,const char *format,...)
972%
973% A description of each parameter follows:
974%
975% o exception: the exception info.
976%
977% o filename: the source module filename.
978%
979% o function: the function name.
980%
981% o line: the line number of the source module.
982%
983% o severity: Specifies the numeric error category.
984%
985% o tag: the locale tag.
986%
987% o format: the output format.
988%
989*/
990
cristy93670402013-02-19 12:42:11 +0000991MagickExport MagickBooleanType ThrowMagickExceptionList(
992 ExceptionInfo *exception,const char *module,const char *function,
993 const size_t line,const ExceptionType severity,const char *tag,
994 const char *format,va_list operands)
cristy3ed852e2009-09-05 21:47:34 +0000995{
996 char
997 message[MaxTextExtent],
998 path[MaxTextExtent],
999 reason[MaxTextExtent];
1000
1001 const char
cristy32cca402010-01-23 04:02:23 +00001002 *locale,
1003 *type;
cristy3ed852e2009-09-05 21:47:34 +00001004
1005 int
1006 n;
1007
1008 MagickBooleanType
1009 status;
1010
1011 size_t
1012 length;
1013
1014 assert(exception != (ExceptionInfo *) NULL);
1015 assert(exception->signature == MagickSignature);
1016 locale=GetLocaleExceptionMessage(severity,tag);
1017 (void) CopyMagickString(reason,locale,MaxTextExtent);
1018 (void) ConcatenateMagickString(reason," ",MaxTextExtent);
1019 length=strlen(reason);
1020#if defined(MAGICKCORE_HAVE_VSNPRINTF)
1021 n=vsnprintf(reason+length,MaxTextExtent-length,format,operands);
1022#else
1023 n=vsprintf(reason+length,format,operands);
1024#endif
1025 if (n < 0)
1026 reason[MaxTextExtent-1]='\0';
1027 status=LogMagickEvent(ExceptionEvent,module,function,line,"%s",reason);
1028 GetPathComponent(module,TailPath,path);
cristy32cca402010-01-23 04:02:23 +00001029 type="undefined";
1030 if ((severity >= WarningException) && (severity < ErrorException))
1031 type="warning";
1032 if ((severity >= ErrorException) && (severity < FatalErrorException))
1033 type="error";
1034 if (severity >= FatalErrorException)
1035 type="fatal";
cristyb51dff52011-05-19 16:55:47 +00001036 (void) FormatLocaleString(message,MaxTextExtent,"%s @ %s/%s/%s/%.20g",reason,
cristye8c25f92010-06-03 00:53:06 +00001037 type,path,function,(double) line);
cristy3ed852e2009-09-05 21:47:34 +00001038 (void) ThrowException(exception,severity,message,(char *) NULL);
1039 return(status);
1040}
1041
1042MagickExport MagickBooleanType ThrowMagickException(ExceptionInfo *exception,
cristybb503372010-05-27 20:51:26 +00001043 const char *module,const char *function,const size_t line,
cristy3ed852e2009-09-05 21:47:34 +00001044 const ExceptionType severity,const char *tag,const char *format,...)
1045{
1046 MagickBooleanType
1047 status;
1048
1049 va_list
1050 operands;
1051
1052 va_start(operands,format);
1053 status=ThrowMagickExceptionList(exception,module,function,line,severity,tag,
1054 format,operands);
1055 va_end(operands);
1056 return(status);
1057}