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