blob: cf8ae32425bf6ea3a44bbcce8061d17ad2979623 [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 %
16% John Cristy %
17% July 1993 %
18% %
19% %
cristy7e41fe82010-12-04 23:12:08 +000020% Copyright 1999-2011 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% %
234+ D e f a u l t E r r o r H a n d l e r %
235% %
236% %
237% %
238%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
239%
240% DefaultErrorHandler() displays an error reason.
241%
242% The format of the DefaultErrorHandler method is:
243%
244% void MagickError(const ExceptionType severity,const char *reason,
245% const char *description)
246%
247% A description of each parameter follows:
248%
249% o severity: Specifies the numeric error category.
250%
251% o reason: Specifies the reason to display before terminating the
252% program.
253%
254% o description: Specifies any description to the reason.
255%
256*/
257static void DefaultErrorHandler(const ExceptionType magick_unused(severity),
258 const char *reason,const char *description)
259{
260 if (reason == (char *) NULL)
261 return;
cristyb51dff52011-05-19 16:55:47 +0000262 (void) FormatLocaleFile(stderr,"%s: %s",GetClientName(),reason);
cristy3ed852e2009-09-05 21:47:34 +0000263 if (description != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +0000264 (void) FormatLocaleFile(stderr," (%s)",description);
265 (void) FormatLocaleFile(stderr,".\n");
cristy3ed852e2009-09-05 21:47:34 +0000266 (void) fflush(stderr);
267}
268
269/*
270%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
271% %
272% %
273% %
274+ D e f a u l t F a t a l E r r o r H a n d l e r %
275% %
276% %
277% %
278%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
279%
280% DefaultFatalErrorHandler() displays an error reason and then terminates the
281% program.
282%
283% The format of the DefaultFatalErrorHandler method is:
284%
285% void MagickFatalError(const ExceptionType severity,const char *reason,
286% const char *description)
287%
288% A description of each parameter follows:
289%
290% o severity: Specifies the numeric error category.
291%
292% o reason: Specifies the reason to display before terminating the
293% program.
294%
295% o description: Specifies any description to the reason.
296%
297*/
298static void DefaultFatalErrorHandler(
299 const ExceptionType magick_unused(severity),
300 const char *reason,const char *description)
301{
302 if (reason == (char *) NULL)
303 return;
cristyb51dff52011-05-19 16:55:47 +0000304 (void) FormatLocaleFile(stderr,"%s: %s",GetClientName(),reason);
cristy3ed852e2009-09-05 21:47:34 +0000305 if (description != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +0000306 (void) FormatLocaleFile(stderr," (%s)",description);
307 (void) FormatLocaleFile(stderr,".\n");
cristy3ed852e2009-09-05 21:47:34 +0000308 (void) fflush(stderr);
309 MagickCoreTerminus();
310 exit(1);
311}
312
313/*
314%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
315% %
316% %
317% %
318+ D e f a u l t W a r n i n g H a n d l e r %
319% %
320% %
321% %
322%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
323%
324% DefaultWarningHandler() displays a warning reason.
325%
326% The format of the DefaultWarningHandler method is:
327%
cristy3b743bb2009-09-14 16:07:59 +0000328% void DefaultWarningHandler(const ExceptionType severity,
cristy3ed852e2009-09-05 21:47:34 +0000329% const char *reason,const char *description)
330%
331% A description of each parameter follows:
332%
cristy3b743bb2009-09-14 16:07:59 +0000333% o severity: Specifies the numeric warning category.
cristy3ed852e2009-09-05 21:47:34 +0000334%
335% o reason: Specifies the reason to display before terminating the
336% program.
337%
338% o description: Specifies any description to the reason.
339%
340*/
341static void DefaultWarningHandler(const ExceptionType magick_unused(severity),
342 const char *reason,const char *description)
343{
344 if (reason == (char *) NULL)
345 return;
cristyb51dff52011-05-19 16:55:47 +0000346 (void) FormatLocaleFile(stderr,"%s: %s",GetClientName(),reason);
cristy3ed852e2009-09-05 21:47:34 +0000347 if (description != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +0000348 (void) FormatLocaleFile(stderr," (%s)",description);
349 (void) FormatLocaleFile(stderr,".\n");
cristy3ed852e2009-09-05 21:47:34 +0000350 (void) fflush(stderr);
351}
352
353/*
354%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
355% %
356% %
357% %
358% D e s t r o y E x c e p t i o n I n f o %
359% %
360% %
361% %
362%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
363%
364% DestroyExceptionInfo() deallocates memory associated with an exception.
365%
366% The format of the DestroyExceptionInfo method is:
367%
368% ExceptionInfo *DestroyExceptionInfo(ExceptionInfo *exception)
369%
370% A description of each parameter follows:
371%
372% o exception: the exception info.
373%
374*/
375MagickExport ExceptionInfo *DestroyExceptionInfo(ExceptionInfo *exception)
376{
377 MagickBooleanType
378 relinquish;
379
380 assert(exception != (ExceptionInfo *) NULL);
381 assert(exception->signature == MagickSignature);
cristy78883b22010-01-11 16:38:53 +0000382 if (exception->semaphore == (SemaphoreInfo *) NULL)
383 AcquireSemaphoreInfo(&exception->semaphore);
cristyf84a1932010-01-03 18:00:18 +0000384 LockSemaphoreInfo(exception->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000385 exception->severity=UndefinedException;
386 if (exception->exceptions != (void *) NULL)
387 exception->exceptions=(void *) DestroyLinkedList((LinkedListInfo *)
388 exception->exceptions,DestroyExceptionElement);
389 relinquish=exception->relinquish;
390 if (exception->relinquish != MagickFalse)
391 exception->signature=(~MagickSignature);
cristyf84a1932010-01-03 18:00:18 +0000392 UnlockSemaphoreInfo(exception->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000393 DestroySemaphoreInfo(&exception->semaphore);
394 if (relinquish != MagickFalse)
395 exception=(ExceptionInfo *) RelinquishMagickMemory(exception);
396 return(exception);
397}
398
399/*
400%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
401% %
402% %
403% %
404% G e t E x c e p t i o n I n f o %
405% %
406% %
407% %
408%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
409%
410% GetExceptionInfo() initializes an exception to default values.
411%
412% The format of the GetExceptionInfo method is:
413%
414% GetExceptionInfo(ExceptionInfo *exception)
415%
416% A description of each parameter follows:
417%
418% o exception: the exception info.
419%
420*/
421MagickExport void GetExceptionInfo(ExceptionInfo *exception)
422{
423 assert(exception != (ExceptionInfo *) NULL);
424 (void) ResetMagickMemory(exception,0,sizeof(*exception));
425 exception->severity=UndefinedException;
426 exception->exceptions=(void *) NewLinkedList(0);
cristy18b17442009-10-25 18:36:48 +0000427 exception->semaphore=AllocateSemaphoreInfo();
cristy3ed852e2009-09-05 21:47:34 +0000428 exception->signature=MagickSignature;
429}
430
431/*
432%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
433% %
434% %
435% %
436% 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)
cristy866a02f2011-09-07 12:10:32 +0000461#if !defined(_GNU_SOURCE)
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;
cristyf84a1932010-01-03 18:00:18 +0000628 LockSemaphoreInfo(exception->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 }
cristyf84a1932010-01-03 18:00:18 +0000638 UnlockSemaphoreInfo(exception->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000639}
640
641/*
642%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
643% %
644% %
645% %
646% M a g i c k E r r o r %
647% %
648% %
649% %
650%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
651%
652% MagickError() calls the exception handler methods with an error reason.
653%
654% The format of the MagickError method is:
655%
656% void MagickError(const ExceptionType error,const char *reason,
657% const char *description)
658%
659% A description of each parameter follows:
660%
661% o exception: Specifies the numeric error category.
662%
663% o reason: Specifies the reason to display before terminating the
664% program.
665%
666% o description: Specifies any description to the reason.
667%
668*/
669MagickExport void MagickError(const ExceptionType error,const char *reason,
670 const char *description)
671{
672 if (error_handler != (ErrorHandler) NULL)
673 (*error_handler)(error,reason,description);
674}
675
676/*
677%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
678% %
679% %
680% %
681% M a g i c k F a t al E r r o r %
682% %
683% %
684% %
685%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
686%
687% MagickFatalError() calls the fatal exception handler methods with an error
688% reason.
689%
690% The format of the MagickError method is:
691%
692% void MagickFatalError(const ExceptionType error,const char *reason,
693% const char *description)
694%
695% A description of each parameter follows:
696%
697% o exception: Specifies the numeric error category.
698%
699% o reason: Specifies the reason to display before terminating the
700% program.
701%
702% o description: Specifies any description to the reason.
703%
704*/
705MagickExport void MagickFatalError(const ExceptionType error,const char *reason,
706 const char *description)
707{
708 if (fatal_error_handler != (ErrorHandler) NULL)
709 (*fatal_error_handler)(error,reason,description);
710}
711
712/*
713%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
714% %
715% %
716% %
717% M a g i c k W a r n i n g %
718% %
719% %
720% %
721%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
722%
723% MagickWarning() calls the warning handler methods with a warning reason.
724%
725% The format of the MagickWarning method is:
726%
727% void MagickWarning(const ExceptionType warning,const char *reason,
728% const char *description)
729%
730% A description of each parameter follows:
731%
732% o warning: the warning severity.
733%
734% o reason: Define the reason for the warning.
735%
736% o description: Describe the warning.
737%
738*/
739MagickExport void MagickWarning(const ExceptionType warning,const char *reason,
740 const char *description)
741{
742 if (warning_handler != (WarningHandler) NULL)
743 (*warning_handler)(warning,reason,description);
744}
745
746/*
747%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
748% %
749% %
750% %
751% S e t E r r o r H a n d l e r %
752% %
753% %
754% %
755%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
756%
757% SetErrorHandler() sets the exception handler to the specified method
758% and returns the previous exception handler.
759%
760% The format of the SetErrorHandler method is:
761%
762% ErrorHandler SetErrorHandler(ErrorHandler handler)
763%
764% A description of each parameter follows:
765%
766% o handler: the method to handle errors.
767%
768*/
769MagickExport ErrorHandler SetErrorHandler(ErrorHandler handler)
770{
771 ErrorHandler
772 previous_handler;
773
774 previous_handler=error_handler;
775 error_handler=handler;
776 return(previous_handler);
777}
778
779/*
780%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
781% %
782% %
783% %
784% S e t F a t a l E r r o r H a n d l e r %
785% %
786% %
787% %
788%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
789%
790% SetFatalErrorHandler() sets the fatal exception handler to the specified
791% method and returns the previous fatal 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 FatalErrorHandler SetFatalErrorHandler(FatalErrorHandler handler)
803{
804 FatalErrorHandler
805 previous_handler;
806
807 previous_handler=fatal_error_handler;
808 fatal_error_handler=handler;
809 return(previous_handler);
810}
811
812/*
813%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
814% %
815% %
816% %
817% S e t W a r n i n g H a n d l e r %
818% %
819% %
820% %
821%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
822%
823% SetWarningHandler() sets the warning handler to the specified method
824% and returns the previous warning handler.
825%
826% The format of the SetWarningHandler method is:
827%
828% ErrorHandler SetWarningHandler(ErrorHandler handler)
829%
830% A description of each parameter follows:
831%
832% o handler: the method to handle warnings.
833%
834*/
835MagickExport WarningHandler SetWarningHandler(WarningHandler handler)
836{
837 WarningHandler
838 previous_handler;
839
840 previous_handler=warning_handler;
841 warning_handler=handler;
842 return(previous_handler);
843}
844
845/*
846%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
847% %
848% %
849% %
850% T h r o w E x c e p t i o n %
851% %
852% %
853% %
854%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
855%
856% ThrowException() throws an exception with the specified severity code,
857% reason, and optional description.
858%
859% The format of the ThrowException method is:
860%
861% MagickBooleanType ThrowException(ExceptionInfo *exception,
862% const ExceptionType severity,const char *reason,
863% const char *description)
864%
865% A description of each parameter follows:
866%
867% o exception: the exception info.
868%
869% o severity: the severity of the exception.
870%
871% o reason: the reason for the exception.
872%
873% o description: the exception description.
874%
875*/
876MagickExport MagickBooleanType ThrowException(ExceptionInfo *exception,
877 const ExceptionType severity,const char *reason,const char *description)
878{
879 register ExceptionInfo
880 *p;
881
882 assert(exception != (ExceptionInfo *) NULL);
883 assert(exception->signature == MagickSignature);
884 p=(ExceptionInfo *) GetLastValueInLinkedList((LinkedListInfo *)
885 exception->exceptions);
886 if ((p != (ExceptionInfo *) NULL) && (p->severity == severity) &&
887 (LocaleCompare(exception->reason,reason) == 0) &&
888 (LocaleCompare(exception->description,description) == 0))
889 return(MagickTrue);
cristy73bd4a52010-10-05 11:24:23 +0000890 p=(ExceptionInfo *) AcquireMagickMemory(sizeof(*p));
cristy3ed852e2009-09-05 21:47:34 +0000891 if (p == (ExceptionInfo *) NULL)
892 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
893 (void) ResetMagickMemory(p,0,sizeof(*p));
894 p->severity=severity;
895 if (reason != (const char *) NULL)
896 p->reason=ConstantString(reason);
897 if (description != (const char *) NULL)
898 p->description=ConstantString(description);
899 p->signature=MagickSignature;
900 (void) AppendValueToLinkedList((LinkedListInfo *) exception->exceptions,p);
901 exception->severity=p->severity;
902 exception->reason=p->reason;
903 exception->description=p->description;
904 return(MagickTrue);
905}
906
907/*
908%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
909% %
910% %
911% %
912% T h r o w M a g i c k E x c e p t i o n %
913% %
914% %
915% %
916%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
917%
918% ThrowMagickException logs an exception as determined by the log configuration
919% file. If an error occurs, MagickFalse is returned otherwise MagickTrue.
920%
921% The format of the ThrowMagickException method is:
922%
923% MagickBooleanType ThrowFileException(ExceptionInfo *exception,
cristybb503372010-05-27 20:51:26 +0000924% const char *module,const char *function,const size_t line,
cristy3ed852e2009-09-05 21:47:34 +0000925% const ExceptionType severity,const char *tag,const char *format,...)
926%
927% A description of each parameter follows:
928%
929% o exception: the exception info.
930%
931% o filename: the source module filename.
932%
933% o function: the function name.
934%
935% o line: the line number of the source module.
936%
937% o severity: Specifies the numeric error category.
938%
939% o tag: the locale tag.
940%
941% o format: the output format.
942%
943*/
944
cristyd1dd6e42011-09-04 01:46:08 +0000945static MagickBooleanType ThrowMagickExceptionList(ExceptionInfo *exception,
946 const char *module,const char *function,const size_t line,
947 const ExceptionType severity,const char *tag,const char *format,
948 va_list operands)
cristy3ed852e2009-09-05 21:47:34 +0000949{
950 char
951 message[MaxTextExtent],
952 path[MaxTextExtent],
953 reason[MaxTextExtent];
954
955 const char
cristy32cca402010-01-23 04:02:23 +0000956 *locale,
957 *type;
cristy3ed852e2009-09-05 21:47:34 +0000958
959 int
960 n;
961
962 MagickBooleanType
963 status;
964
965 size_t
966 length;
967
968 assert(exception != (ExceptionInfo *) NULL);
969 assert(exception->signature == MagickSignature);
970 locale=GetLocaleExceptionMessage(severity,tag);
971 (void) CopyMagickString(reason,locale,MaxTextExtent);
972 (void) ConcatenateMagickString(reason," ",MaxTextExtent);
973 length=strlen(reason);
974#if defined(MAGICKCORE_HAVE_VSNPRINTF)
975 n=vsnprintf(reason+length,MaxTextExtent-length,format,operands);
976#else
977 n=vsprintf(reason+length,format,operands);
978#endif
979 if (n < 0)
980 reason[MaxTextExtent-1]='\0';
981 status=LogMagickEvent(ExceptionEvent,module,function,line,"%s",reason);
982 GetPathComponent(module,TailPath,path);
cristy32cca402010-01-23 04:02:23 +0000983 type="undefined";
984 if ((severity >= WarningException) && (severity < ErrorException))
985 type="warning";
986 if ((severity >= ErrorException) && (severity < FatalErrorException))
987 type="error";
988 if (severity >= FatalErrorException)
989 type="fatal";
cristyb51dff52011-05-19 16:55:47 +0000990 (void) FormatLocaleString(message,MaxTextExtent,"%s @ %s/%s/%s/%.20g",reason,
cristye8c25f92010-06-03 00:53:06 +0000991 type,path,function,(double) line);
cristy3ed852e2009-09-05 21:47:34 +0000992 (void) ThrowException(exception,severity,message,(char *) NULL);
993 return(status);
994}
995
996MagickExport MagickBooleanType ThrowMagickException(ExceptionInfo *exception,
cristybb503372010-05-27 20:51:26 +0000997 const char *module,const char *function,const size_t line,
cristy3ed852e2009-09-05 21:47:34 +0000998 const ExceptionType severity,const char *tag,const char *format,...)
999{
1000 MagickBooleanType
1001 status;
1002
1003 va_list
1004 operands;
1005
1006 va_start(operands,format);
1007 status=ThrowMagickExceptionList(exception,module,function,line,severity,tag,
1008 format,operands);
1009 va_end(operands);
1010 return(status);
1011}