blob: bcc656b9934ad9a7a97ae1719cc5fd2835ec3822 [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");
dirke31feb82014-06-20 11:03:07 +0000110 InitializeExceptionInfo(exception);
cristy3ed852e2009-09-05 21:47:34 +0000111 exception->relinquish=MagickTrue;
112 return(exception);
113}
114
dirke31feb82014-06-20 11:03:07 +0000115/*l
cristy3ed852e2009-09-05 21:47:34 +0000116%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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{
cristy3ed852e2009-09-05 21:47:34 +0000155 assert(exception != (ExceptionInfo *) NULL);
156 assert(exception->signature == MagickSignature);
dirk3efeece2014-04-27 16:42:54 +0000157 if (exception->exceptions == (void *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000158 return;
cristyf84a1932010-01-03 18:00:18 +0000159 LockSemaphoreInfo(exception->semaphore);
dirk3efeece2014-04-27 16:42:54 +0000160 ClearLinkedList((LinkedListInfo *) exception->exceptions,
cristyf135cd62014-06-15 11:21:31 +0000161 DestroyExceptionElement);
cristy3ed852e2009-09-05 21:47:34 +0000162 exception->severity=UndefinedException;
163 exception->reason=(char *) NULL;
164 exception->description=(char *) NULL;
cristyf84a1932010-01-03 18:00:18 +0000165 UnlockSemaphoreInfo(exception->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000166 errno=0;
167}
168
169/*
170%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
171% %
172% %
173% %
174% C a t c h E x c e p t i o n %
175% %
176% %
177% %
178%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
179%
180% CatchException() returns if no exceptions is found otherwise it reports
181% the exception as a warning, error, or fatal depending on the severity.
182%
183% The format of the CatchException method is:
184%
185% CatchException(ExceptionInfo *exception)
186%
187% A description of each parameter follows:
188%
189% o exception: the exception info.
190%
191*/
192MagickExport void CatchException(ExceptionInfo *exception)
193{
194 register const ExceptionInfo
195 *p;
196
197 assert(exception != (ExceptionInfo *) NULL);
198 assert(exception->signature == MagickSignature);
199 if (exception->exceptions == (void *) NULL)
200 return;
cristyf84a1932010-01-03 18:00:18 +0000201 LockSemaphoreInfo(exception->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000202 ResetLinkedListIterator((LinkedListInfo *) exception->exceptions);
203 p=(const ExceptionInfo *) GetNextValueInLinkedList((LinkedListInfo *)
204 exception->exceptions);
205 while (p != (const ExceptionInfo *) NULL)
206 {
207 if ((p->severity >= WarningException) && (p->severity < ErrorException))
208 MagickWarning(p->severity,p->reason,p->description);
209 if ((p->severity >= ErrorException) && (p->severity < FatalErrorException))
210 MagickError(p->severity,p->reason,p->description);
cristy32cca402010-01-23 04:02:23 +0000211 if (p->severity >= FatalErrorException)
cristy3ed852e2009-09-05 21:47:34 +0000212 MagickFatalError(p->severity,p->reason,p->description);
213 p=(const ExceptionInfo *) GetNextValueInLinkedList((LinkedListInfo *)
214 exception->exceptions);
215 }
cristyf84a1932010-01-03 18:00:18 +0000216 UnlockSemaphoreInfo(exception->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000217 ClearMagickException(exception);
218}
219
220/*
221%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
222% %
223% %
224% %
cristyc82a27b2011-10-21 01:07:16 +0000225% C l o n e E x c e p t i o n I n f o %
226% %
227% %
228% %
229%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
230%
231% CloneExceptionInfo() clones the ExceptionInfo structure.
232%
233% The format of the CloneExceptionInfo method is:
234%
235% ExceptionInfo *CloneException(ExceptionInfo *exception)
236%
237% A description of each parameter follows:
238%
239% o exception: the exception info.
240%
241*/
242MagickExport ExceptionInfo *CloneExceptionInfo(ExceptionInfo *exception)
243{
244 ExceptionInfo
245 *clone_exception;
246
247 clone_exception=(ExceptionInfo *) AcquireMagickMemory(sizeof(*exception));
248 if (clone_exception == (ExceptionInfo *) NULL)
249 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
dirke31feb82014-06-20 11:03:07 +0000250 InitializeExceptionInfo(clone_exception);
cristyc82a27b2011-10-21 01:07:16 +0000251 InheritException(clone_exception,exception);
cristy4592b2c2014-01-12 14:12:01 +0000252 clone_exception->relinquish=MagickTrue;
cristya0dfced2014-01-12 15:22:46 +0000253 return(clone_exception);
cristyc82a27b2011-10-21 01:07:16 +0000254}
255
256/*
257%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
258% %
259% %
260% %
cristy3ed852e2009-09-05 21:47:34 +0000261+ D e f a u l t E r r o r H a n d l e r %
262% %
263% %
264% %
265%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
266%
267% DefaultErrorHandler() displays an error reason.
268%
269% The format of the DefaultErrorHandler method is:
270%
271% void MagickError(const ExceptionType severity,const char *reason,
272% const char *description)
273%
274% A description of each parameter follows:
275%
276% o severity: Specifies the numeric error category.
277%
278% o reason: Specifies the reason to display before terminating the
279% program.
280%
281% o description: Specifies any description to the reason.
282%
283*/
284static void DefaultErrorHandler(const ExceptionType magick_unused(severity),
285 const char *reason,const char *description)
286{
287 if (reason == (char *) NULL)
288 return;
cristyb51dff52011-05-19 16:55:47 +0000289 (void) FormatLocaleFile(stderr,"%s: %s",GetClientName(),reason);
cristy3ed852e2009-09-05 21:47:34 +0000290 if (description != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +0000291 (void) FormatLocaleFile(stderr," (%s)",description);
292 (void) FormatLocaleFile(stderr,".\n");
cristy3ed852e2009-09-05 21:47:34 +0000293 (void) fflush(stderr);
294}
295
296/*
297%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
298% %
299% %
300% %
301+ D e f a u l t F a t a l E r r o r H a n d l e r %
302% %
303% %
304% %
305%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
306%
307% DefaultFatalErrorHandler() displays an error reason and then terminates the
308% program.
309%
310% The format of the DefaultFatalErrorHandler method is:
311%
312% void MagickFatalError(const ExceptionType severity,const char *reason,
313% const char *description)
314%
315% A description of each parameter follows:
316%
317% o severity: Specifies the numeric error category.
318%
cristyb200b6c2012-12-13 15:20:26 +0000319% o reason: Specifies the reason to display before terminating the program.
cristy3ed852e2009-09-05 21:47:34 +0000320%
321% o description: Specifies any description to the reason.
322%
323*/
cristyb200b6c2012-12-13 15:20:26 +0000324static void DefaultFatalErrorHandler(const ExceptionType severity,
cristy3ed852e2009-09-05 21:47:34 +0000325 const char *reason,const char *description)
326{
327 if (reason == (char *) NULL)
328 return;
cristyb51dff52011-05-19 16:55:47 +0000329 (void) FormatLocaleFile(stderr,"%s: %s",GetClientName(),reason);
cristy3ed852e2009-09-05 21:47:34 +0000330 if (description != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +0000331 (void) FormatLocaleFile(stderr," (%s)",description);
332 (void) FormatLocaleFile(stderr,".\n");
cristy3ed852e2009-09-05 21:47:34 +0000333 (void) fflush(stderr);
334 MagickCoreTerminus();
cristyb4d552c2012-12-13 15:42:17 +0000335 exit((int) (severity-FatalErrorException)+1);
cristy3ed852e2009-09-05 21:47:34 +0000336}
337
338/*
339%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
340% %
341% %
342% %
343+ D e f a u l t W a r n i n g H a n d l e r %
344% %
345% %
346% %
347%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
348%
349% DefaultWarningHandler() displays a warning reason.
350%
351% The format of the DefaultWarningHandler method is:
352%
cristy3b743bb2009-09-14 16:07:59 +0000353% void DefaultWarningHandler(const ExceptionType severity,
cristy3ed852e2009-09-05 21:47:34 +0000354% const char *reason,const char *description)
355%
356% A description of each parameter follows:
357%
cristy3b743bb2009-09-14 16:07:59 +0000358% o severity: Specifies the numeric warning category.
cristy3ed852e2009-09-05 21:47:34 +0000359%
360% o reason: Specifies the reason to display before terminating the
361% program.
362%
363% o description: Specifies any description to the reason.
364%
365*/
366static void DefaultWarningHandler(const ExceptionType magick_unused(severity),
367 const char *reason,const char *description)
368{
369 if (reason == (char *) NULL)
370 return;
cristyb51dff52011-05-19 16:55:47 +0000371 (void) FormatLocaleFile(stderr,"%s: %s",GetClientName(),reason);
cristy3ed852e2009-09-05 21:47:34 +0000372 if (description != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +0000373 (void) FormatLocaleFile(stderr," (%s)",description);
374 (void) FormatLocaleFile(stderr,".\n");
cristy3ed852e2009-09-05 21:47:34 +0000375 (void) fflush(stderr);
376}
377
378/*
379%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
380% %
381% %
382% %
383% D e s t r o y E x c e p t i o n I n f o %
384% %
385% %
386% %
387%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
388%
389% DestroyExceptionInfo() deallocates memory associated with an exception.
390%
391% The format of the DestroyExceptionInfo method is:
392%
393% ExceptionInfo *DestroyExceptionInfo(ExceptionInfo *exception)
394%
395% A description of each parameter follows:
396%
397% o exception: the exception info.
398%
399*/
400MagickExport ExceptionInfo *DestroyExceptionInfo(ExceptionInfo *exception)
401{
402 MagickBooleanType
403 relinquish;
404
405 assert(exception != (ExceptionInfo *) NULL);
406 assert(exception->signature == MagickSignature);
cristy78883b22010-01-11 16:38:53 +0000407 if (exception->semaphore == (SemaphoreInfo *) NULL)
cristy04b11db2014-02-16 15:10:39 +0000408 ActivateSemaphoreInfo(&exception->semaphore);
cristyf84a1932010-01-03 18:00:18 +0000409 LockSemaphoreInfo(exception->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000410 exception->severity=UndefinedException;
cristy3ed852e2009-09-05 21:47:34 +0000411 if (exception->relinquish != MagickFalse)
dirkcee811c2014-04-19 18:50:49 +0000412 {
413 exception->signature=(~MagickSignature);
414 if (exception->exceptions != (void *) NULL)
415 exception->exceptions=(void *) DestroyLinkedList((LinkedListInfo *)
416 exception->exceptions,DestroyExceptionElement);
417 }
418 else if (exception->exceptions != (void *) NULL)
419 ClearLinkedList((LinkedListInfo *) exception->exceptions,
420 DestroyExceptionElement);
421 relinquish=exception->relinquish;
cristyf84a1932010-01-03 18:00:18 +0000422 UnlockSemaphoreInfo(exception->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000423 if (relinquish != MagickFalse)
dirkcee811c2014-04-19 18:50:49 +0000424 {
425 RelinquishSemaphoreInfo(&exception->semaphore);
426 exception=(ExceptionInfo *) RelinquishMagickMemory(exception);
427 }
cristy3ed852e2009-09-05 21:47:34 +0000428 return(exception);
429}
430
431/*
432%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
433% %
434% %
435% %
cristy3ed852e2009-09-05 21:47:34 +0000436% G e t E x c e p t i o n M e s s a g e %
437% %
438% %
439% %
440%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
441%
442% GetExceptionMessage() returns the error message defined by the specified
443% error code.
444%
445% The format of the GetExceptionMessage method is:
446%
447% char *GetExceptionMessage(const int error)
448%
449% A description of each parameter follows:
450%
451% o error: the error code.
452%
453*/
454MagickExport char *GetExceptionMessage(const int error)
455{
456 char
457 exception[MaxTextExtent];
458
cristyb5641692010-04-08 22:49:59 +0000459 *exception='\0';
cristy3ed852e2009-09-05 21:47:34 +0000460#if defined(MAGICKCORE_HAVE_STRERROR_R)
cristy7d4a1d62011-10-13 15:54:12 +0000461#if !defined(MAGICKCORE_STRERROR_R_CHAR_P)
cristy3ed852e2009-09-05 21:47:34 +0000462 (void) strerror_r(error,exception,sizeof(exception));
463#else
cristy866a02f2011-09-07 12:10:32 +0000464 (void) CopyMagickString(exception,strerror_r(error,exception,
465 sizeof(exception)),sizeof(exception));
466#endif
467#else
cristy3ed852e2009-09-05 21:47:34 +0000468 (void) CopyMagickString(exception,strerror(error),sizeof(exception));
469#endif
470 return(ConstantString(exception));
471}
472
473/*
474%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
475% %
476% %
477% %
478% G e t L o c a l e E x c e p t i o n M e s s a g e %
479% %
480% %
481% %
482%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
483%
484% GetLocaleExceptionMessage() converts a enumerated exception severity and tag
485% to a message in the current locale.
486%
487% The format of the GetLocaleExceptionMessage method is:
488%
489% const char *GetLocaleExceptionMessage(const ExceptionType severity,
490% const char *tag)
491%
492% A description of each parameter follows:
493%
494% o severity: the severity of the exception.
495%
496% o tag: the message tag.
497%
498*/
499
500static const char *ExceptionSeverityToTag(const ExceptionType severity)
501{
502 switch (severity)
503 {
504 case ResourceLimitWarning: return("Resource/Limit/Warning/");
505 case TypeWarning: return("Type/Warning/");
506 case OptionWarning: return("Option/Warning/");
507 case DelegateWarning: return("Delegate/Warning/");
508 case MissingDelegateWarning: return("Missing/Delegate/Warning/");
509 case CorruptImageWarning: return("Corrupt/Image/Warning/");
510 case FileOpenWarning: return("File/Open/Warning/");
511 case BlobWarning: return("Blob/Warning/");
512 case StreamWarning: return("Stream/Warning/");
513 case CacheWarning: return("Cache/Warning/");
514 case CoderWarning: return("Coder/Warning/");
cristy992729d2010-01-01 15:45:06 +0000515 case FilterWarning: return("Filter/Warning/");
cristy3ed852e2009-09-05 21:47:34 +0000516 case ModuleWarning: return("Module/Warning/");
517 case DrawWarning: return("Draw/Warning/");
518 case ImageWarning: return("Image/Warning/");
519 case WandWarning: return("Wand/Warning/");
520 case XServerWarning: return("XServer/Warning/");
521 case MonitorWarning: return("Monitor/Warning/");
522 case RegistryWarning: return("Registry/Warning/");
523 case ConfigureWarning: return("Configure/Warning/");
524 case PolicyWarning: return("Policy/Warning/");
525 case ResourceLimitError: return("Resource/Limit/Error/");
526 case TypeError: return("Type/Error/");
527 case OptionError: return("Option/Error/");
528 case DelegateError: return("Delegate/Error/");
529 case MissingDelegateError: return("Missing/Delegate/Error/");
530 case CorruptImageError: return("Corrupt/Image/Error/");
531 case FileOpenError: return("File/Open/Error/");
532 case BlobError: return("Blob/Error/");
533 case StreamError: return("Stream/Error/");
534 case CacheError: return("Cache/Error/");
535 case CoderError: return("Coder/Error/");
cristy992729d2010-01-01 15:45:06 +0000536 case FilterError: return("Filter/Error/");
cristy3ed852e2009-09-05 21:47:34 +0000537 case ModuleError: return("Module/Error/");
538 case DrawError: return("Draw/Error/");
539 case ImageError: return("Image/Error/");
540 case WandError: return("Wand/Error/");
541 case XServerError: return("XServer/Error/");
542 case MonitorError: return("Monitor/Error/");
543 case RegistryError: return("Registry/Error/");
544 case ConfigureError: return("Configure/Error/");
545 case PolicyError: return("Policy/Error/");
546 case ResourceLimitFatalError: return("Resource/Limit/FatalError/");
547 case TypeFatalError: return("Type/FatalError/");
548 case OptionFatalError: return("Option/FatalError/");
549 case DelegateFatalError: return("Delegate/FatalError/");
550 case MissingDelegateFatalError: return("Missing/Delegate/FatalError/");
551 case CorruptImageFatalError: return("Corrupt/Image/FatalError/");
552 case FileOpenFatalError: return("File/Open/FatalError/");
553 case BlobFatalError: return("Blob/FatalError/");
554 case StreamFatalError: return("Stream/FatalError/");
555 case CacheFatalError: return("Cache/FatalError/");
556 case CoderFatalError: return("Coder/FatalError/");
cristy992729d2010-01-01 15:45:06 +0000557 case FilterFatalError: return("Filter/FatalError/");
cristy3ed852e2009-09-05 21:47:34 +0000558 case ModuleFatalError: return("Module/FatalError/");
559 case DrawFatalError: return("Draw/FatalError/");
560 case ImageFatalError: return("Image/FatalError/");
561 case WandFatalError: return("Wand/FatalError/");
562 case XServerFatalError: return("XServer/FatalError/");
563 case MonitorFatalError: return("Monitor/FatalError/");
564 case RegistryFatalError: return("Registry/FatalError/");
565 case ConfigureFatalError: return("Configure/FatalError/");
566 case PolicyFatalError: return("Policy/FatalError/");
567 default: break;
568 }
569 return("");
570}
571
572MagickExport const char *GetLocaleExceptionMessage(const ExceptionType severity,
573 const char *tag)
574{
575 char
576 message[MaxTextExtent];
577
578 const char
579 *locale_message;
580
581 assert(tag != (const char *) NULL);
cristyb51dff52011-05-19 16:55:47 +0000582 (void) FormatLocaleString(message,MaxTextExtent,"Exception/%s%s",
cristy3ed852e2009-09-05 21:47:34 +0000583 ExceptionSeverityToTag(severity),tag);
584 locale_message=GetLocaleMessage(message);
585 if (locale_message == (const char *) NULL)
586 return(tag);
587 if (locale_message == message)
588 return(tag);
589 return(locale_message);
590}
591
592/*
593%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
594% %
595% %
596% %
597% I n h e r i t E x c e p t i o n %
598% %
599% %
600% %
601%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
602%
603% InheritException() inherits an exception from a related exception.
604%
605% The format of the InheritException method is:
606%
607% InheritException(ExceptionInfo *exception,const ExceptionInfo *relative)
608%
609% A description of each parameter follows:
610%
611% o exception: the exception info.
612%
613% o relative: the related exception info.
614%
615*/
616MagickExport void InheritException(ExceptionInfo *exception,
617 const ExceptionInfo *relative)
618{
619 register const ExceptionInfo
620 *p;
621
622 assert(exception != (ExceptionInfo *) NULL);
623 assert(exception->signature == MagickSignature);
624 assert(relative != (ExceptionInfo *) NULL);
625 assert(relative->signature == MagickSignature);
626 if (relative->exceptions == (void *) NULL)
627 return;
cristy93670402013-02-19 12:42:11 +0000628 LockSemaphoreInfo(relative->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000629 ResetLinkedListIterator((LinkedListInfo *) relative->exceptions);
630 p=(const ExceptionInfo *) GetNextValueInLinkedList((LinkedListInfo *)
631 relative->exceptions);
632 while (p != (const ExceptionInfo *) NULL)
633 {
634 (void) ThrowException(exception,p->severity,p->reason,p->description);
635 p=(const ExceptionInfo *) GetNextValueInLinkedList((LinkedListInfo *)
636 relative->exceptions);
637 }
cristy93670402013-02-19 12:42:11 +0000638 UnlockSemaphoreInfo(relative->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000639}
640
641/*
642%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
643% %
644% %
645% %
dirke31feb82014-06-20 11:03:07 +0000646% I n i t i a l i z e t E x c e p t i o n I n f o %
647% %
648% %
649% %
650%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
651%
652% InitializeExceptionInfo() initializes an exception to default values.
653%
654% The format of the InitializeExceptionInfo method is:
655%
656% InitializeExceptionInfo(ExceptionInfo *exception)
657%
658% A description of each parameter follows:
659%
660% o exception: the exception info.
661%
662*/
663MagickPrivate void InitializeExceptionInfo(ExceptionInfo *exception)
664{
665 assert(exception != (ExceptionInfo *) NULL);
666 (void) ResetMagickMemory(exception,0,sizeof(*exception));
667 exception->severity=UndefinedException;
668 exception->exceptions=(void *) NewLinkedList(0);
669 exception->semaphore=AcquireSemaphoreInfo();
670 exception->signature=MagickSignature;
671}
672
673/*
674%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
675% %
676% %
677% %
cristy3ed852e2009-09-05 21:47:34 +0000678% M a g i c k E r r o r %
679% %
680% %
681% %
682%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
683%
684% MagickError() calls the exception handler methods with an error reason.
685%
686% The format of the MagickError method is:
687%
688% void MagickError(const ExceptionType error,const char *reason,
689% const char *description)
690%
691% A description of each parameter follows:
692%
693% o exception: Specifies the numeric error category.
694%
695% o reason: Specifies the reason to display before terminating the
696% program.
697%
698% o description: Specifies any description to the reason.
699%
700*/
701MagickExport void MagickError(const ExceptionType error,const char *reason,
702 const char *description)
703{
704 if (error_handler != (ErrorHandler) NULL)
705 (*error_handler)(error,reason,description);
706}
707
708/*
709%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
710% %
711% %
712% %
713% M a g i c k F a t al E r r o r %
714% %
715% %
716% %
717%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
718%
719% MagickFatalError() calls the fatal exception handler methods with an error
720% reason.
721%
722% The format of the MagickError method is:
723%
724% void MagickFatalError(const ExceptionType error,const char *reason,
725% const char *description)
726%
727% A description of each parameter follows:
728%
729% o exception: Specifies the numeric error category.
730%
731% o reason: Specifies the reason to display before terminating the
732% program.
733%
734% o description: Specifies any description to the reason.
735%
736*/
737MagickExport void MagickFatalError(const ExceptionType error,const char *reason,
738 const char *description)
739{
740 if (fatal_error_handler != (ErrorHandler) NULL)
741 (*fatal_error_handler)(error,reason,description);
742}
743
744/*
745%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
746% %
747% %
748% %
749% M a g i c k W a r n i n g %
750% %
751% %
752% %
753%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
754%
755% MagickWarning() calls the warning handler methods with a warning reason.
756%
757% The format of the MagickWarning method is:
758%
759% void MagickWarning(const ExceptionType warning,const char *reason,
760% const char *description)
761%
762% A description of each parameter follows:
763%
764% o warning: the warning severity.
765%
766% o reason: Define the reason for the warning.
767%
768% o description: Describe the warning.
769%
770*/
771MagickExport void MagickWarning(const ExceptionType warning,const char *reason,
772 const char *description)
773{
774 if (warning_handler != (WarningHandler) NULL)
775 (*warning_handler)(warning,reason,description);
776}
777
778/*
779%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
780% %
781% %
782% %
783% S e t E r r o r H a n d l e r %
784% %
785% %
786% %
787%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
788%
789% SetErrorHandler() sets the exception handler to the specified method
790% and returns the previous exception handler.
791%
792% The format of the SetErrorHandler method is:
793%
794% ErrorHandler SetErrorHandler(ErrorHandler handler)
795%
796% A description of each parameter follows:
797%
798% o handler: the method to handle errors.
799%
800*/
801MagickExport ErrorHandler SetErrorHandler(ErrorHandler handler)
802{
803 ErrorHandler
804 previous_handler;
805
806 previous_handler=error_handler;
807 error_handler=handler;
808 return(previous_handler);
809}
810
811/*
812%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
813% %
814% %
815% %
816% S e t F a t a l E r r o r H a n d l e r %
817% %
818% %
819% %
820%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
821%
822% SetFatalErrorHandler() sets the fatal exception handler to the specified
823% method and returns the previous fatal exception handler.
824%
825% The format of the SetErrorHandler method is:
826%
827% ErrorHandler SetErrorHandler(ErrorHandler handler)
828%
829% A description of each parameter follows:
830%
831% o handler: the method to handle errors.
832%
833*/
834MagickExport FatalErrorHandler SetFatalErrorHandler(FatalErrorHandler handler)
835{
836 FatalErrorHandler
837 previous_handler;
838
839 previous_handler=fatal_error_handler;
840 fatal_error_handler=handler;
841 return(previous_handler);
842}
843
844/*
845%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
846% %
847% %
848% %
849% S e t W a r n i n g H a n d l e r %
850% %
851% %
852% %
853%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
854%
855% SetWarningHandler() sets the warning handler to the specified method
856% and returns the previous warning handler.
857%
858% The format of the SetWarningHandler method is:
859%
860% ErrorHandler SetWarningHandler(ErrorHandler handler)
861%
862% A description of each parameter follows:
863%
864% o handler: the method to handle warnings.
865%
866*/
867MagickExport WarningHandler SetWarningHandler(WarningHandler handler)
868{
869 WarningHandler
870 previous_handler;
871
872 previous_handler=warning_handler;
873 warning_handler=handler;
874 return(previous_handler);
875}
876
877/*
878%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
879% %
880% %
881% %
882% T h r o w E x c e p t i o n %
883% %
884% %
885% %
886%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
887%
888% ThrowException() throws an exception with the specified severity code,
889% reason, and optional description.
890%
891% The format of the ThrowException method is:
892%
893% MagickBooleanType ThrowException(ExceptionInfo *exception,
894% const ExceptionType severity,const char *reason,
895% const char *description)
896%
897% A description of each parameter follows:
898%
899% o exception: the exception info.
900%
901% o severity: the severity of the exception.
902%
903% o reason: the reason for the exception.
904%
905% o description: the exception description.
906%
907*/
908MagickExport MagickBooleanType ThrowException(ExceptionInfo *exception,
909 const ExceptionType severity,const char *reason,const char *description)
910{
911 register ExceptionInfo
912 *p;
913
914 assert(exception != (ExceptionInfo *) NULL);
915 assert(exception->signature == MagickSignature);
cristy93670402013-02-19 12:42:11 +0000916 LockSemaphoreInfo(exception->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000917 p=(ExceptionInfo *) GetLastValueInLinkedList((LinkedListInfo *)
918 exception->exceptions);
919 if ((p != (ExceptionInfo *) NULL) && (p->severity == severity) &&
920 (LocaleCompare(exception->reason,reason) == 0) &&
921 (LocaleCompare(exception->description,description) == 0))
cristy93670402013-02-19 12:42:11 +0000922 {
923 UnlockSemaphoreInfo(exception->semaphore);
924 return(MagickTrue);
925 }
cristy73bd4a52010-10-05 11:24:23 +0000926 p=(ExceptionInfo *) AcquireMagickMemory(sizeof(*p));
cristy3ed852e2009-09-05 21:47:34 +0000927 if (p == (ExceptionInfo *) NULL)
cristy93670402013-02-19 12:42:11 +0000928 {
929 UnlockSemaphoreInfo(exception->semaphore);
930 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
931 }
cristy3ed852e2009-09-05 21:47:34 +0000932 (void) ResetMagickMemory(p,0,sizeof(*p));
933 p->severity=severity;
934 if (reason != (const char *) NULL)
935 p->reason=ConstantString(reason);
936 if (description != (const char *) NULL)
937 p->description=ConstantString(description);
938 p->signature=MagickSignature;
939 (void) AppendValueToLinkedList((LinkedListInfo *) exception->exceptions,p);
cristy992f5372013-05-15 12:20:19 +0000940 if (p->severity >= exception->severity)
941 {
942 exception->severity=p->severity;
943 exception->reason=p->reason;
944 exception->description=p->description;
945 }
cristy93670402013-02-19 12:42:11 +0000946 UnlockSemaphoreInfo(exception->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000947 return(MagickTrue);
948}
949
950/*
951%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
952% %
953% %
954% %
955% T h r o w M a g i c k E x c e p t i o n %
956% %
957% %
958% %
959%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
960%
anthony5216f822012-04-10 13:02:37 +0000961% ThrowMagickException logs an exception as determined by the log
962% configuration file. If an error occurs, MagickFalse is returned
963% otherwise MagickTrue.
cristy3ed852e2009-09-05 21:47:34 +0000964%
965% The format of the ThrowMagickException method is:
966%
967% MagickBooleanType ThrowFileException(ExceptionInfo *exception,
cristybb503372010-05-27 20:51:26 +0000968% const char *module,const char *function,const size_t line,
cristy3ed852e2009-09-05 21:47:34 +0000969% const ExceptionType severity,const char *tag,const char *format,...)
970%
971% A description of each parameter follows:
972%
973% o exception: the exception info.
974%
975% o filename: the source module filename.
976%
977% o function: the function name.
978%
979% o line: the line number of the source module.
980%
981% o severity: Specifies the numeric error category.
982%
983% o tag: the locale tag.
984%
985% o format: the output format.
986%
987*/
988
cristy93670402013-02-19 12:42:11 +0000989MagickExport MagickBooleanType ThrowMagickExceptionList(
990 ExceptionInfo *exception,const char *module,const char *function,
991 const size_t line,const ExceptionType severity,const char *tag,
992 const char *format,va_list operands)
cristy3ed852e2009-09-05 21:47:34 +0000993{
994 char
995 message[MaxTextExtent],
996 path[MaxTextExtent],
997 reason[MaxTextExtent];
998
999 const char
cristy32cca402010-01-23 04:02:23 +00001000 *locale,
1001 *type;
cristy3ed852e2009-09-05 21:47:34 +00001002
1003 int
1004 n;
1005
1006 MagickBooleanType
1007 status;
1008
1009 size_t
1010 length;
1011
1012 assert(exception != (ExceptionInfo *) NULL);
1013 assert(exception->signature == MagickSignature);
1014 locale=GetLocaleExceptionMessage(severity,tag);
1015 (void) CopyMagickString(reason,locale,MaxTextExtent);
1016 (void) ConcatenateMagickString(reason," ",MaxTextExtent);
1017 length=strlen(reason);
1018#if defined(MAGICKCORE_HAVE_VSNPRINTF)
1019 n=vsnprintf(reason+length,MaxTextExtent-length,format,operands);
1020#else
1021 n=vsprintf(reason+length,format,operands);
1022#endif
1023 if (n < 0)
1024 reason[MaxTextExtent-1]='\0';
1025 status=LogMagickEvent(ExceptionEvent,module,function,line,"%s",reason);
1026 GetPathComponent(module,TailPath,path);
cristy32cca402010-01-23 04:02:23 +00001027 type="undefined";
1028 if ((severity >= WarningException) && (severity < ErrorException))
1029 type="warning";
1030 if ((severity >= ErrorException) && (severity < FatalErrorException))
1031 type="error";
1032 if (severity >= FatalErrorException)
1033 type="fatal";
cristyb51dff52011-05-19 16:55:47 +00001034 (void) FormatLocaleString(message,MaxTextExtent,"%s @ %s/%s/%s/%.20g",reason,
cristye8c25f92010-06-03 00:53:06 +00001035 type,path,function,(double) line);
cristy3ed852e2009-09-05 21:47:34 +00001036 (void) ThrowException(exception,severity,message,(char *) NULL);
1037 return(status);
1038}
1039
1040MagickExport MagickBooleanType ThrowMagickException(ExceptionInfo *exception,
cristybb503372010-05-27 20:51:26 +00001041 const char *module,const char *function,const size_t line,
cristy3ed852e2009-09-05 21:47:34 +00001042 const ExceptionType severity,const char *tag,const char *format,...)
1043{
1044 MagickBooleanType
1045 status;
1046
1047 va_list
1048 operands;
1049
1050 va_start(operands,format);
1051 status=ThrowMagickExceptionList(exception,module,function,line,severity,tag,
1052 format,operands);
1053 va_end(operands);
1054 return(status);
1055}