Coverage Report

Created: 2026-03-31 06:56

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