blob: 973741a896037c41aa91ccf89ca43df4f14b0b9c [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% %
cristyb56bb242014-11-25 17:12:48 +000020% Copyright 1999-2015 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);
cristye1c94d92015-06-28 12:16:33 +0000156 assert(exception->signature == MagickCoreSignature);
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);
cristye1c94d92015-06-28 12:16:33 +0000198 assert(exception->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +0000199 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);
cristye1c94d92015-06-28 12:16:33 +0000406 assert(exception->signature == MagickCoreSignature);
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 {
cristye1c94d92015-06-28 12:16:33 +0000413 exception->signature=(~MagickCoreSignature);
dirkcee811c2014-04-19 18:50:49 +0000414 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
cristy151b66d2015-04-15 10:50:31 +0000457 exception[MagickPathExtent];
cristy3ed852e2009-09-05 21:47:34 +0000458
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
cristy151b66d2015-04-15 10:50:31 +0000576 message[MagickPathExtent];
cristy3ed852e2009-09-05 21:47:34 +0000577
578 const char
579 *locale_message;
580
581 assert(tag != (const char *) NULL);
cristy151b66d2015-04-15 10:50:31 +0000582 (void) FormatLocaleString(message,MagickPathExtent,"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);
cristye1c94d92015-06-28 12:16:33 +0000623 assert(exception->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +0000624 assert(relative != (ExceptionInfo *) NULL);
cristye1c94d92015-06-28 12:16:33 +0000625 assert(relative->signature == MagickCoreSignature);
dirkf078e392014-11-06 21:55:10 +0000626 assert(exception != relative);
cristy3ed852e2009-09-05 21:47:34 +0000627 if (relative->exceptions == (void *) NULL)
628 return;
cristy93670402013-02-19 12:42:11 +0000629 LockSemaphoreInfo(relative->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000630 ResetLinkedListIterator((LinkedListInfo *) relative->exceptions);
631 p=(const ExceptionInfo *) GetNextValueInLinkedList((LinkedListInfo *)
632 relative->exceptions);
633 while (p != (const ExceptionInfo *) NULL)
634 {
635 (void) ThrowException(exception,p->severity,p->reason,p->description);
636 p=(const ExceptionInfo *) GetNextValueInLinkedList((LinkedListInfo *)
637 relative->exceptions);
638 }
cristy93670402013-02-19 12:42:11 +0000639 UnlockSemaphoreInfo(relative->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000640}
641
642/*
643%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
644% %
645% %
646% %
dirke31feb82014-06-20 11:03:07 +0000647% I n i t i a l i z e t E x c e p t i o n I n f o %
648% %
649% %
650% %
651%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
652%
653% InitializeExceptionInfo() initializes an exception to default values.
654%
655% The format of the InitializeExceptionInfo method is:
656%
657% InitializeExceptionInfo(ExceptionInfo *exception)
658%
659% A description of each parameter follows:
660%
661% o exception: the exception info.
662%
663*/
664MagickPrivate void InitializeExceptionInfo(ExceptionInfo *exception)
665{
666 assert(exception != (ExceptionInfo *) NULL);
667 (void) ResetMagickMemory(exception,0,sizeof(*exception));
668 exception->severity=UndefinedException;
669 exception->exceptions=(void *) NewLinkedList(0);
670 exception->semaphore=AcquireSemaphoreInfo();
cristye1c94d92015-06-28 12:16:33 +0000671 exception->signature=MagickCoreSignature;
dirke31feb82014-06-20 11:03:07 +0000672}
673
674/*
675%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
676% %
677% %
678% %
cristy3ed852e2009-09-05 21:47:34 +0000679% M a g i c k E r r o r %
680% %
681% %
682% %
683%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
684%
685% MagickError() calls the exception handler methods with an error reason.
686%
687% The format of the MagickError method is:
688%
689% void MagickError(const ExceptionType error,const char *reason,
690% const char *description)
691%
692% A description of each parameter follows:
693%
694% o exception: Specifies the numeric error category.
695%
696% o reason: Specifies the reason to display before terminating the
697% program.
698%
699% o description: Specifies any description to the reason.
700%
701*/
702MagickExport void MagickError(const ExceptionType error,const char *reason,
703 const char *description)
704{
705 if (error_handler != (ErrorHandler) NULL)
706 (*error_handler)(error,reason,description);
707}
708
709/*
710%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
711% %
712% %
713% %
714% M a g i c k F a t al E r r o r %
715% %
716% %
717% %
718%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
719%
720% MagickFatalError() calls the fatal exception handler methods with an error
721% reason.
722%
723% The format of the MagickError method is:
724%
725% void MagickFatalError(const ExceptionType error,const char *reason,
726% const char *description)
727%
728% A description of each parameter follows:
729%
730% o exception: Specifies the numeric error category.
731%
732% o reason: Specifies the reason to display before terminating the
733% program.
734%
735% o description: Specifies any description to the reason.
736%
737*/
738MagickExport void MagickFatalError(const ExceptionType error,const char *reason,
739 const char *description)
740{
741 if (fatal_error_handler != (ErrorHandler) NULL)
742 (*fatal_error_handler)(error,reason,description);
743}
744
745/*
746%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
747% %
748% %
749% %
750% M a g i c k W a r n i n g %
751% %
752% %
753% %
754%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
755%
756% MagickWarning() calls the warning handler methods with a warning reason.
757%
758% The format of the MagickWarning method is:
759%
760% void MagickWarning(const ExceptionType warning,const char *reason,
761% const char *description)
762%
763% A description of each parameter follows:
764%
765% o warning: the warning severity.
766%
767% o reason: Define the reason for the warning.
768%
769% o description: Describe the warning.
770%
771*/
772MagickExport void MagickWarning(const ExceptionType warning,const char *reason,
773 const char *description)
774{
775 if (warning_handler != (WarningHandler) NULL)
776 (*warning_handler)(warning,reason,description);
777}
778
779/*
780%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
781% %
782% %
783% %
784% S e t E r r o r H a n d l e r %
785% %
786% %
787% %
788%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
789%
790% SetErrorHandler() sets the exception handler to the specified method
791% and returns the previous exception handler.
792%
793% The format of the SetErrorHandler method is:
794%
795% ErrorHandler SetErrorHandler(ErrorHandler handler)
796%
797% A description of each parameter follows:
798%
799% o handler: the method to handle errors.
800%
801*/
802MagickExport ErrorHandler SetErrorHandler(ErrorHandler handler)
803{
804 ErrorHandler
805 previous_handler;
806
807 previous_handler=error_handler;
808 error_handler=handler;
809 return(previous_handler);
810}
811
812/*
813%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
814% %
815% %
816% %
817% S e t F a t a l E r r o r H a n d l e r %
818% %
819% %
820% %
821%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
822%
823% SetFatalErrorHandler() sets the fatal exception handler to the specified
824% method and returns the previous fatal exception handler.
825%
826% The format of the SetErrorHandler method is:
827%
828% ErrorHandler SetErrorHandler(ErrorHandler handler)
829%
830% A description of each parameter follows:
831%
832% o handler: the method to handle errors.
833%
834*/
835MagickExport FatalErrorHandler SetFatalErrorHandler(FatalErrorHandler handler)
836{
837 FatalErrorHandler
838 previous_handler;
839
840 previous_handler=fatal_error_handler;
841 fatal_error_handler=handler;
842 return(previous_handler);
843}
844
845/*
846%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
847% %
848% %
849% %
850% S e t W a r n i n g H a n d l e r %
851% %
852% %
853% %
854%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
855%
856% SetWarningHandler() sets the warning handler to the specified method
857% and returns the previous warning handler.
858%
859% The format of the SetWarningHandler method is:
860%
861% ErrorHandler SetWarningHandler(ErrorHandler handler)
862%
863% A description of each parameter follows:
864%
865% o handler: the method to handle warnings.
866%
867*/
868MagickExport WarningHandler SetWarningHandler(WarningHandler handler)
869{
870 WarningHandler
871 previous_handler;
872
873 previous_handler=warning_handler;
874 warning_handler=handler;
875 return(previous_handler);
876}
877
878/*
879%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
880% %
881% %
882% %
883% T h r o w E x c e p t i o n %
884% %
885% %
886% %
887%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
888%
889% ThrowException() throws an exception with the specified severity code,
890% reason, and optional description.
891%
892% The format of the ThrowException method is:
893%
894% MagickBooleanType ThrowException(ExceptionInfo *exception,
895% const ExceptionType severity,const char *reason,
896% const char *description)
897%
898% A description of each parameter follows:
899%
900% o exception: the exception info.
901%
902% o severity: the severity of the exception.
903%
904% o reason: the reason for the exception.
905%
906% o description: the exception description.
907%
908*/
909MagickExport MagickBooleanType ThrowException(ExceptionInfo *exception,
910 const ExceptionType severity,const char *reason,const char *description)
911{
912 register ExceptionInfo
913 *p;
914
915 assert(exception != (ExceptionInfo *) NULL);
cristye1c94d92015-06-28 12:16:33 +0000916 assert(exception->signature == MagickCoreSignature);
cristy93670402013-02-19 12:42:11 +0000917 LockSemaphoreInfo(exception->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000918 p=(ExceptionInfo *) GetLastValueInLinkedList((LinkedListInfo *)
919 exception->exceptions);
920 if ((p != (ExceptionInfo *) NULL) && (p->severity == severity) &&
921 (LocaleCompare(exception->reason,reason) == 0) &&
922 (LocaleCompare(exception->description,description) == 0))
cristy93670402013-02-19 12:42:11 +0000923 {
924 UnlockSemaphoreInfo(exception->semaphore);
925 return(MagickTrue);
926 }
cristy73bd4a52010-10-05 11:24:23 +0000927 p=(ExceptionInfo *) AcquireMagickMemory(sizeof(*p));
cristy3ed852e2009-09-05 21:47:34 +0000928 if (p == (ExceptionInfo *) NULL)
cristy93670402013-02-19 12:42:11 +0000929 {
930 UnlockSemaphoreInfo(exception->semaphore);
931 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
932 }
cristy3ed852e2009-09-05 21:47:34 +0000933 (void) ResetMagickMemory(p,0,sizeof(*p));
934 p->severity=severity;
935 if (reason != (const char *) NULL)
936 p->reason=ConstantString(reason);
937 if (description != (const char *) NULL)
938 p->description=ConstantString(description);
cristye1c94d92015-06-28 12:16:33 +0000939 p->signature=MagickCoreSignature;
cristy3ed852e2009-09-05 21:47:34 +0000940 (void) AppendValueToLinkedList((LinkedListInfo *) exception->exceptions,p);
cristy992f5372013-05-15 12:20:19 +0000941 if (p->severity >= exception->severity)
942 {
943 exception->severity=p->severity;
944 exception->reason=p->reason;
945 exception->description=p->description;
946 }
cristy93670402013-02-19 12:42:11 +0000947 UnlockSemaphoreInfo(exception->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000948 return(MagickTrue);
949}
950
951/*
952%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
953% %
954% %
955% %
956% T h r o w M a g i c k E x c e p t i o n %
957% %
958% %
959% %
960%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
961%
anthony5216f822012-04-10 13:02:37 +0000962% ThrowMagickException logs an exception as determined by the log
963% configuration file. If an error occurs, MagickFalse is returned
964% otherwise MagickTrue.
cristy3ed852e2009-09-05 21:47:34 +0000965%
966% The format of the ThrowMagickException method is:
967%
968% MagickBooleanType ThrowFileException(ExceptionInfo *exception,
cristybb503372010-05-27 20:51:26 +0000969% const char *module,const char *function,const size_t line,
cristy3ed852e2009-09-05 21:47:34 +0000970% const ExceptionType severity,const char *tag,const char *format,...)
971%
972% A description of each parameter follows:
973%
974% o exception: the exception info.
975%
976% o filename: the source module filename.
977%
978% o function: the function name.
979%
980% o line: the line number of the source module.
981%
982% o severity: Specifies the numeric error category.
983%
984% o tag: the locale tag.
985%
986% o format: the output format.
987%
988*/
989
cristy93670402013-02-19 12:42:11 +0000990MagickExport MagickBooleanType ThrowMagickExceptionList(
991 ExceptionInfo *exception,const char *module,const char *function,
992 const size_t line,const ExceptionType severity,const char *tag,
993 const char *format,va_list operands)
cristy3ed852e2009-09-05 21:47:34 +0000994{
995 char
cristy151b66d2015-04-15 10:50:31 +0000996 message[MagickPathExtent],
997 path[MagickPathExtent],
998 reason[MagickPathExtent];
cristy3ed852e2009-09-05 21:47:34 +0000999
1000 const char
cristy32cca402010-01-23 04:02:23 +00001001 *locale,
1002 *type;
cristy3ed852e2009-09-05 21:47:34 +00001003
1004 int
1005 n;
1006
1007 MagickBooleanType
1008 status;
1009
1010 size_t
1011 length;
1012
1013 assert(exception != (ExceptionInfo *) NULL);
cristye1c94d92015-06-28 12:16:33 +00001014 assert(exception->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +00001015 locale=GetLocaleExceptionMessage(severity,tag);
cristy151b66d2015-04-15 10:50:31 +00001016 (void) CopyMagickString(reason,locale,MagickPathExtent);
1017 (void) ConcatenateMagickString(reason," ",MagickPathExtent);
cristy3ed852e2009-09-05 21:47:34 +00001018 length=strlen(reason);
1019#if defined(MAGICKCORE_HAVE_VSNPRINTF)
cristy151b66d2015-04-15 10:50:31 +00001020 n=vsnprintf(reason+length,MagickPathExtent-length,format,operands);
cristy3ed852e2009-09-05 21:47:34 +00001021#else
1022 n=vsprintf(reason+length,format,operands);
1023#endif
1024 if (n < 0)
cristy151b66d2015-04-15 10:50:31 +00001025 reason[MagickPathExtent-1]='\0';
cristy3ed852e2009-09-05 21:47:34 +00001026 status=LogMagickEvent(ExceptionEvent,module,function,line,"%s",reason);
1027 GetPathComponent(module,TailPath,path);
cristy32cca402010-01-23 04:02:23 +00001028 type="undefined";
1029 if ((severity >= WarningException) && (severity < ErrorException))
1030 type="warning";
1031 if ((severity >= ErrorException) && (severity < FatalErrorException))
1032 type="error";
1033 if (severity >= FatalErrorException)
1034 type="fatal";
cristy151b66d2015-04-15 10:50:31 +00001035 (void) FormatLocaleString(message,MagickPathExtent,"%s @ %s/%s/%s/%.20g",reason,
cristye8c25f92010-06-03 00:53:06 +00001036 type,path,function,(double) line);
cristy3ed852e2009-09-05 21:47:34 +00001037 (void) ThrowException(exception,severity,message,(char *) NULL);
1038 return(status);
1039}
1040
1041MagickExport MagickBooleanType ThrowMagickException(ExceptionInfo *exception,
cristybb503372010-05-27 20:51:26 +00001042 const char *module,const char *function,const size_t line,
cristy3ed852e2009-09-05 21:47:34 +00001043 const ExceptionType severity,const char *tag,const char *format,...)
1044{
1045 MagickBooleanType
1046 status;
1047
1048 va_list
1049 operands;
1050
1051 va_start(operands,format);
1052 status=ThrowMagickExceptionList(exception,module,function,line,severity,tag,
1053 format,operands);
1054 va_end(operands);
1055 return(status);
1056}