MagickCore  6.9.12-58
Convert, Edit, Or Compose Bitmap Images
 All Data Structures
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-2021 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  DefaultWarningHandler(const ExceptionType,const char *,const char *);
72 
73 #if defined(__cplusplus) || defined(c_plusplus)
74 }
75 #endif
76 
77 /*
78  Global declarations.
79 */
80 static ErrorHandler
81  error_handler = DefaultErrorHandler;
82 
83 static FatalErrorHandler
84  fatal_error_handler = DefaultFatalErrorHandler;
85 
86 static WarningHandler
87  warning_handler = DefaultWarningHandler;
88 
89 /*
90  Static declarations.
91 */
92 static SemaphoreInfo
93  *exception_semaphore = (SemaphoreInfo *) NULL;
94 
95 /*
96 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
97 % %
98 % %
99 % %
100 % A c q u i r e E x c e p t i o n I n f o %
101 % %
102 % %
103 % %
104 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
105 %
106 % AcquireExceptionInfo() allocates the ExceptionInfo structure.
107 %
108 % The format of the AcquireExceptionInfo method is:
109 %
110 % ExceptionInfo *AcquireExceptionInfo(void)
111 %
112 */
113 MagickExport ExceptionInfo *AcquireExceptionInfo(void)
114 {
116  *exception;
117 
118  exception=(ExceptionInfo *) AcquireMagickMemory(sizeof(*exception));
119  if (exception == (ExceptionInfo *) NULL)
120  ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
121  InitializeExceptionInfo(exception);
122  exception->relinquish=MagickTrue;
123  return(exception);
124 }
125 
126 /*
127 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
128 % %
129 % %
130 % %
131 % C l e a r M a g i c k E x c e p t i o n %
132 % %
133 % %
134 % %
135 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
136 %
137 % ClearMagickException() clears any exception that may not have been caught
138 % yet.
139 %
140 % The format of the ClearMagickException method is:
141 %
142 % ClearMagickException(ExceptionInfo *exception)
143 %
144 % A description of each parameter follows:
145 %
146 % o exception: the exception info.
147 %
148 */
149 
150 static void *DestroyExceptionElement(void *exception)
151 {
153  *p;
154 
155  p=(ExceptionInfo *) exception;
156  if (p->reason != (char *) NULL)
157  p->reason=DestroyString(p->reason);
158  if (p->description != (char *) NULL)
159  p->description=DestroyString(p->description);
160  p=(ExceptionInfo *) RelinquishMagickMemory(p);
161  return((void *) NULL);
162 }
163 
164 MagickExport void ClearMagickException(ExceptionInfo *exception)
165 {
166  assert(exception != (ExceptionInfo *) NULL);
167  assert(exception->signature == MagickCoreSignature);
168  if (exception->exceptions == (void *) NULL)
169  return;
170  LockSemaphoreInfo(exception->semaphore);
171  ClearLinkedList((LinkedListInfo *) exception->exceptions,
172  DestroyExceptionElement);
173  exception->severity=UndefinedException;
174  exception->reason=(char *) NULL;
175  exception->description=(char *) NULL;
176  UnlockSemaphoreInfo(exception->semaphore);
177  errno=0;
178 }
179 
180 /*
181 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
182 % %
183 % %
184 % %
185 % C a t c h E x c e p t i o n %
186 % %
187 % %
188 % %
189 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
190 %
191 % CatchException() returns if no exceptions is found otherwise it reports
192 % the exception as a warning, error, or fatal depending on the severity.
193 %
194 % The format of the CatchException method is:
195 %
196 % CatchException(ExceptionInfo *exception)
197 %
198 % A description of each parameter follows:
199 %
200 % o exception: the exception info.
201 %
202 */
203 MagickExport void CatchException(ExceptionInfo *exception)
204 {
206  *exceptions;
207 
208  const ExceptionInfo
209  *p;
210 
211  ssize_t
212  i;
213 
214  assert(exception != (ExceptionInfo *) NULL);
215  assert(exception->signature == MagickCoreSignature);
216  if (exception->exceptions == (void *) NULL)
217  return;
218  LockSemaphoreInfo(exception->semaphore);
219  exceptions=(LinkedListInfo *) exception->exceptions;
220  ResetLinkedListIterator(exceptions);
221  p=(const ExceptionInfo *) GetNextValueInLinkedList(exceptions);
222  for (i=0; p != (const ExceptionInfo *) NULL; i++)
223  {
224  if (p->severity >= FatalErrorException)
225  MagickFatalError(p->severity,p->reason,p->description);
226  if ((p->severity >= ErrorException) && (p->severity < FatalErrorException))
227  MagickError(p->severity,p->reason,p->description);
228  if ((p->severity >= WarningException) && (p->severity < ErrorException))
229  MagickWarning(p->severity,p->reason,p->description);
230  p=(const ExceptionInfo *) GetNextValueInLinkedList(exceptions);
231  }
232  UnlockSemaphoreInfo(exception->semaphore);
233  ClearMagickException(exception);
234 }
235 
236 /*
237 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
238 % %
239 % %
240 % %
241 % C l o n e E x c e p t i o n I n f o %
242 % %
243 % %
244 % %
245 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
246 %
247 % CloneExceptionInfo() clones the ExceptionInfo structure.
248 %
249 % The format of the CloneExceptionInfo method is:
250 %
251 % ExceptionInfo *CloneException(ExceptionInfo *exception)
252 %
253 % A description of each parameter follows:
254 %
255 % o exception: the exception info.
256 %
257 */
258 MagickExport ExceptionInfo *CloneExceptionInfo(ExceptionInfo *exception)
259 {
261  *clone_exception;
262 
263  clone_exception=(ExceptionInfo *) AcquireMagickMemory(sizeof(*exception));
264  if (clone_exception == (ExceptionInfo *) NULL)
265  ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
266  InitializeExceptionInfo(clone_exception);
267  InheritException(clone_exception,exception);
268  clone_exception->relinquish=MagickTrue;
269  return(clone_exception);
270 }
271 
272 /*
273 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
274 % %
275 % %
276 % %
277 + D e f a u l t E r r o r H a n d l e r %
278 % %
279 % %
280 % %
281 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
282 %
283 % DefaultErrorHandler() displays an error reason.
284 %
285 % The format of the DefaultErrorHandler method is:
286 %
287 % void MagickError(const ExceptionType severity,const char *reason,
288 % const char *description)
289 %
290 % A description of each parameter follows:
291 %
292 % o severity: Specifies the numeric error category.
293 %
294 % o reason: Specifies the reason to display before terminating the
295 % program.
296 %
297 % o description: Specifies any description to the reason.
298 %
299 */
300 static void DefaultErrorHandler(const ExceptionType magick_unused(severity),
301  const char *reason,const char *description)
302 {
303  magick_unreferenced(severity);
304 
305  if (reason == (char *) NULL)
306  return;
307  (void) FormatLocaleFile(stderr,"%s: %s",GetClientName(),reason);
308  if (description != (char *) NULL)
309  (void) FormatLocaleFile(stderr," (%s)",description);
310  (void) FormatLocaleFile(stderr,".\n");
311  (void) fflush(stderr);
312 }
313 
314 /*
315 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
316 % %
317 % %
318 % %
319 + D e f a u l t F a t a l E r r o r H a n d l e r %
320 % %
321 % %
322 % %
323 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
324 %
325 % DefaultFatalErrorHandler() displays an error reason and then terminates the
326 % program.
327 %
328 % The format of the DefaultFatalErrorHandler method is:
329 %
330 % void MagickFatalError(const ExceptionType severity,const char *reason,
331 % const char *description)
332 %
333 % A description of each parameter follows:
334 %
335 % o severity: Specifies the numeric error category.
336 %
337 % o reason: Specifies the reason to display before terminating the program.
338 %
339 % o description: Specifies any description to the reason.
340 %
341 */
342 static void DefaultFatalErrorHandler(const ExceptionType severity,
343  const char *reason,const char *description)
344 {
345  if (reason == (char *) NULL)
346  return;
347  (void) FormatLocaleFile(stderr,"%s: %s",GetClientName(),reason);
348  if (description != (char *) NULL)
349  (void) FormatLocaleFile(stderr," (%s)",description);
350  (void) FormatLocaleFile(stderr,".\n");
351  (void) fflush(stderr);
352  MagickCoreTerminus();
353  exit((int) (severity-FatalErrorException)+1);
354 }
355 
356 /*
357 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
358 % %
359 % %
360 % %
361 + D e f a u l t W a r n i n g H a n d l e r %
362 % %
363 % %
364 % %
365 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
366 %
367 % DefaultWarningHandler() displays a warning reason.
368 %
369 % The format of the DefaultWarningHandler method is:
370 %
371 % void DefaultWarningHandler(const ExceptionType severity,
372 % const char *reason,const char *description)
373 %
374 % A description of each parameter follows:
375 %
376 % o severity: Specifies the numeric warning category.
377 %
378 % o reason: Specifies the reason to display before terminating the
379 % program.
380 %
381 % o description: Specifies any description to the reason.
382 %
383 */
384 static void DefaultWarningHandler(const ExceptionType magick_unused(severity),
385  const char *reason,const char *description)
386 {
387  magick_unreferenced(severity);
388 
389  if (reason == (char *) NULL)
390  return;
391  (void) FormatLocaleFile(stderr,"%s: %s",GetClientName(),reason);
392  if (description != (char *) NULL)
393  (void) FormatLocaleFile(stderr," (%s)",description);
394  (void) FormatLocaleFile(stderr,".\n");
395  (void) fflush(stderr);
396 }
397 
398 /*
399 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
400 % %
401 % %
402 % %
403 % D e s t r o y E x c e p t i o n I n f o %
404 % %
405 % %
406 % %
407 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
408 %
409 % DestroyExceptionInfo() deallocates memory associated with an exception.
410 %
411 % The format of the DestroyExceptionInfo method is:
412 %
413 % ExceptionInfo *DestroyExceptionInfo(ExceptionInfo *exception)
414 %
415 % A description of each parameter follows:
416 %
417 % o exception: the exception info.
418 %
419 */
420 
421 MagickPrivate MagickBooleanType ClearExceptionInfo(ExceptionInfo *exception,
422  MagickBooleanType relinquish)
423 {
424  assert(exception != (ExceptionInfo *) NULL);
425  assert(exception->signature == MagickCoreSignature);
426  if (exception->semaphore == (SemaphoreInfo *) NULL)
427  ActivateSemaphoreInfo(&exception->semaphore);
428  LockSemaphoreInfo(exception->semaphore);
429  if (relinquish == MagickFalse)
430  relinquish=exception->relinquish;
431  exception->severity=UndefinedException;
432  if (relinquish != MagickFalse)
433  {
434  exception->signature=(~MagickCoreSignature);
435  if (exception->exceptions != (void *) NULL)
436  exception->exceptions=(void *) DestroyLinkedList((LinkedListInfo *)
437  exception->exceptions,DestroyExceptionElement);
438  }
439  else if (exception->exceptions != (void *) NULL)
440  ClearLinkedList((LinkedListInfo *) exception->exceptions,
441  DestroyExceptionElement);
442  UnlockSemaphoreInfo(exception->semaphore);
443  if (relinquish != MagickFalse)
444  DestroySemaphoreInfo(&exception->semaphore);
445  return(relinquish);
446 }
447 
448 MagickExport ExceptionInfo *DestroyExceptionInfo(ExceptionInfo *exception)
449 {
450  if (ClearExceptionInfo(exception,MagickFalse) != MagickFalse)
451  exception=(ExceptionInfo *) RelinquishMagickMemory(exception);
452  return(exception);
453 }
454 
455 /*
456 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
457 % %
458 % %
459 % %
460 + 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 %
461 % %
462 % %
463 % %
464 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
465 %
466 % ExceptionComponentGenesis() instantiates the exception component.
467 %
468 % The format of the ExceptionComponentGenesis method is:
469 %
470 % MagickBooleanType ExceptionComponentGenesis(void)
471 %
472 */
473 MagickPrivate MagickBooleanType ExceptionComponentGenesis(void)
474 {
475  if (exception_semaphore == (SemaphoreInfo *) NULL)
476  exception_semaphore=AllocateSemaphoreInfo();
477  return(MagickTrue);
478 }
479 
480 /*
481 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
482 % %
483 % %
484 % %
485 + 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 %
486 % %
487 % %
488 % %
489 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
490 %
491 % ExceptionComponentTerminus() destroys the exception component.
492 %
493 % The format of the ExceptionComponentTerminus method is:
494 %
495 % void ExceptionComponentTerminus(void)
496 %
497 */
498 MagickPrivate void ExceptionComponentTerminus(void)
499 {
500  if (exception_semaphore == (SemaphoreInfo *) NULL)
501  ActivateSemaphoreInfo(&exception_semaphore);
502  LockSemaphoreInfo(exception_semaphore);
503  UnlockSemaphoreInfo(exception_semaphore);
504  DestroySemaphoreInfo(&exception_semaphore);
505 }
506 
507 /*
508 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
509 % %
510 % %
511 % %
512 % G e t E x c e p t i o n M e s s a g e %
513 % %
514 % %
515 % %
516 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
517 %
518 % GetExceptionMessage() returns the error message defined by the specified
519 % error code.
520 %
521 % The format of the GetExceptionMessage method is:
522 %
523 % char *GetExceptionMessage(const int error)
524 %
525 % A description of each parameter follows:
526 %
527 % o error: the error code.
528 %
529 */
530 MagickExport char *GetExceptionMessage(const int error)
531 {
532  char
533  exception[MaxTextExtent];
534 
535  *exception='\0';
536 #if defined(MAGICKCORE_HAVE_STRERROR_R)
537 #if !defined(MAGICKCORE_STRERROR_R_CHAR_P)
538  (void) strerror_r(error,exception,sizeof(exception));
539 #else
540  (void) CopyMagickString(exception,strerror_r(error,exception,
541  sizeof(exception)),sizeof(exception));
542 #endif
543 #else
544  (void) CopyMagickString(exception,strerror(error),sizeof(exception));
545 #endif
546  return(ConstantString(exception));
547 }
548 
549 /*
550 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
551 % %
552 % %
553 % %
554 % 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 %
555 % %
556 % %
557 % %
558 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
559 %
560 % GetLocaleExceptionMessage() converts a enumerated exception severity and tag
561 % to a message in the current locale.
562 %
563 % The format of the GetLocaleExceptionMessage method is:
564 %
565 % const char *GetLocaleExceptionMessage(const ExceptionType severity,
566 % const char *tag)
567 %
568 % A description of each parameter follows:
569 %
570 % o severity: the severity of the exception.
571 %
572 % o tag: the message tag.
573 %
574 */
575 
576 static const char *ExceptionSeverityToTag(const ExceptionType severity)
577 {
578  switch (severity)
579  {
580  case ResourceLimitWarning: return("Resource/Limit/Warning/");
581  case TypeWarning: return("Type/Warning/");
582  case OptionWarning: return("Option/Warning/");
583  case DelegateWarning: return("Delegate/Warning/");
584  case MissingDelegateWarning: return("Missing/Delegate/Warning/");
585  case CorruptImageWarning: return("Corrupt/Image/Warning/");
586  case FileOpenWarning: return("File/Open/Warning/");
587  case BlobWarning: return("Blob/Warning/");
588  case StreamWarning: return("Stream/Warning/");
589  case CacheWarning: return("Cache/Warning/");
590  case CoderWarning: return("Coder/Warning/");
591  case FilterWarning: return("Filter/Warning/");
592  case ModuleWarning: return("Module/Warning/");
593  case DrawWarning: return("Draw/Warning/");
594  case ImageWarning: return("Image/Warning/");
595  case WandWarning: return("Wand/Warning/");
596  case XServerWarning: return("XServer/Warning/");
597  case MonitorWarning: return("Monitor/Warning/");
598  case RegistryWarning: return("Registry/Warning/");
599  case ConfigureWarning: return("Configure/Warning/");
600  case PolicyWarning: return("Policy/Warning/");
601  case ResourceLimitError: return("Resource/Limit/Error/");
602  case TypeError: return("Type/Error/");
603  case OptionError: return("Option/Error/");
604  case DelegateError: return("Delegate/Error/");
605  case MissingDelegateError: return("Missing/Delegate/Error/");
606  case CorruptImageError: return("Corrupt/Image/Error/");
607  case FileOpenError: return("File/Open/Error/");
608  case BlobError: return("Blob/Error/");
609  case StreamError: return("Stream/Error/");
610  case CacheError: return("Cache/Error/");
611  case CoderError: return("Coder/Error/");
612  case FilterError: return("Filter/Error/");
613  case ModuleError: return("Module/Error/");
614  case DrawError: return("Draw/Error/");
615  case ImageError: return("Image/Error/");
616  case WandError: return("Wand/Error/");
617  case XServerError: return("XServer/Error/");
618  case MonitorError: return("Monitor/Error/");
619  case RegistryError: return("Registry/Error/");
620  case ConfigureError: return("Configure/Error/");
621  case PolicyError: return("Policy/Error/");
622  case ResourceLimitFatalError: return("Resource/Limit/FatalError/");
623  case TypeFatalError: return("Type/FatalError/");
624  case OptionFatalError: return("Option/FatalError/");
625  case DelegateFatalError: return("Delegate/FatalError/");
626  case MissingDelegateFatalError: return("Missing/Delegate/FatalError/");
627  case CorruptImageFatalError: return("Corrupt/Image/FatalError/");
628  case FileOpenFatalError: return("File/Open/FatalError/");
629  case BlobFatalError: return("Blob/FatalError/");
630  case StreamFatalError: return("Stream/FatalError/");
631  case CacheFatalError: return("Cache/FatalError/");
632  case CoderFatalError: return("Coder/FatalError/");
633  case FilterFatalError: return("Filter/FatalError/");
634  case ModuleFatalError: return("Module/FatalError/");
635  case DrawFatalError: return("Draw/FatalError/");
636  case ImageFatalError: return("Image/FatalError/");
637  case WandFatalError: return("Wand/FatalError/");
638  case XServerFatalError: return("XServer/FatalError/");
639  case MonitorFatalError: return("Monitor/FatalError/");
640  case RegistryFatalError: return("Registry/FatalError/");
641  case ConfigureFatalError: return("Configure/FatalError/");
642  case PolicyFatalError: return("Policy/FatalError/");
643  default: break;
644  }
645  return("");
646 }
647 
648 MagickExport const char *GetLocaleExceptionMessage(const ExceptionType severity,
649  const char *tag)
650 {
651  char
652  message[MaxTextExtent];
653 
654  const char
655  *locale_message;
656 
657  assert(tag != (const char *) NULL);
658  (void) FormatLocaleString(message,MaxTextExtent,"Exception/%s%s",
659  ExceptionSeverityToTag(severity),tag);
660  locale_message=GetLocaleMessage(message);
661  if (locale_message == (const char *) NULL)
662  return(tag);
663  if (locale_message == message)
664  return(tag);
665  return(locale_message);
666 }
667 
668 /*
669 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
670 % %
671 % %
672 % %
673 % I n h e r i t E x c e p t i o n %
674 % %
675 % %
676 % %
677 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
678 %
679 % InheritException() inherits an exception from a related exception.
680 %
681 % The format of the InheritException method is:
682 %
683 % InheritException(ExceptionInfo *exception,const ExceptionInfo *relative)
684 %
685 % A description of each parameter follows:
686 %
687 % o exception: the exception info.
688 %
689 % o relative: the related exception info.
690 %
691 */
692 MagickExport void InheritException(ExceptionInfo *exception,
693  const ExceptionInfo *relative)
694 {
695  const ExceptionInfo
696  *p;
697 
698  assert(exception != (ExceptionInfo *) NULL);
699  assert(exception->signature == MagickCoreSignature);
700  assert(relative != (ExceptionInfo *) NULL);
701  assert(relative->signature == MagickCoreSignature);
702  assert(exception != relative);
703  if (relative->exceptions == (void *) NULL)
704  return;
705  LockSemaphoreInfo(relative->semaphore);
706  ResetLinkedListIterator((LinkedListInfo *) relative->exceptions);
707  p=(const ExceptionInfo *) GetNextValueInLinkedList((LinkedListInfo *)
708  relative->exceptions);
709  while (p != (const ExceptionInfo *) NULL)
710  {
711  (void) ThrowException(exception,p->severity,p->reason,p->description);
712  p=(const ExceptionInfo *) GetNextValueInLinkedList((LinkedListInfo *)
713  relative->exceptions);
714  }
715  UnlockSemaphoreInfo(relative->semaphore);
716 }
717 
718 /*
719 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
720 % %
721 % %
722 % %
723 % I n i t i a l i z e E x c e p t i o n I n f o %
724 % %
725 % %
726 % %
727 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
728 %
729 % InitializeExceptionInfo() initializes an exception to default values.
730 %
731 % The format of the InitializeExceptionInfo method is:
732 %
733 % InitializeExceptionInfo(ExceptionInfo *exception)
734 %
735 % A description of each parameter follows:
736 %
737 % o exception: the exception info.
738 %
739 */
740 MagickPrivate void InitializeExceptionInfo(ExceptionInfo *exception)
741 {
742  assert(exception != (ExceptionInfo *) NULL);
743  (void) memset(exception,0,sizeof(*exception));
744  exception->severity=UndefinedException;
745  exception->exceptions=(void *) NewLinkedList(0);
746  exception->semaphore=AllocateSemaphoreInfo();
747  exception->signature=MagickCoreSignature;
748 }
749 
750 /*
751 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
752 % %
753 % %
754 % %
755 % M a g i c k E r r o r %
756 % %
757 % %
758 % %
759 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
760 %
761 % MagickError() calls the exception handler methods with an error reason.
762 %
763 % The format of the MagickError method is:
764 %
765 % void MagickError(const ExceptionType error,const char *reason,
766 % const char *description)
767 %
768 % A description of each parameter follows:
769 %
770 % o exception: Specifies the numeric error category.
771 %
772 % o reason: Specifies the reason to display before terminating the
773 % program.
774 %
775 % o description: Specifies any description to the reason.
776 %
777 */
778 MagickExport void MagickError(const ExceptionType error,const char *reason,
779  const char *description)
780 {
781  if (error_handler != (ErrorHandler) NULL)
782  (*error_handler)(error,reason,description);
783 }
784 
785 /*
786 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
787 % %
788 % %
789 % %
790 % M a g i c k F a t al E r r o r %
791 % %
792 % %
793 % %
794 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
795 %
796 % MagickFatalError() calls the fatal exception handler methods with an error
797 % reason.
798 %
799 % The format of the MagickError method is:
800 %
801 % void MagickFatalError(const ExceptionType error,const char *reason,
802 % const char *description)
803 %
804 % A description of each parameter follows:
805 %
806 % o exception: Specifies the numeric error category.
807 %
808 % o reason: Specifies the reason to display before terminating the
809 % program.
810 %
811 % o description: Specifies any description to the reason.
812 %
813 */
814 MagickExport void MagickFatalError(const ExceptionType error,const char *reason,
815  const char *description)
816 {
817  if (fatal_error_handler != (ErrorHandler) NULL)
818  (*fatal_error_handler)(error,reason,description);
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 }