]> granicus.if.org Git - imagemagick/blob - MagickCore/coder.c
Removed invalid assert.
[imagemagick] / MagickCore / coder.c
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 %                                                                             %
4 %                                                                             %
5 %                                                                             %
6 %                   CCCC   OOO   DDDD    EEEEE  RRRR                          %
7 %                  C      O   O  D   D   E      R   R                         %
8 %                  C      O   O  D   D   EEE    RRRR                          %
9 %                  C      O   O  D   D   E      R R                           %
10 %                   CCCC   OOO   DDDD    EEEEE  R  R                          %
11 %                                                                             %
12 %                                                                             %
13 %                     MagickCore Image Coder Methods                          %
14 %                                                                             %
15 %                              Software Design                                %
16 %                                   Cristy                                    %
17 %                                 May 2001                                    %
18 %                                                                             %
19 %                                                                             %
20 %  Copyright 1999-2017 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://www.imagemagick.org/script/license.php                           %
27 %                                                                             %
28 %  Unless required by applicable law or agreed to in writing, software        %
29 %  distributed under the License is distributed on an "AS IS" BASIS,          %
30 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
31 %  See the License for the specific language governing permissions and        %
32 %  limitations under the License.                                             %
33 %                                                                             %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35 %
36 %
37 */
38 \f
39 /*
40   Include declarations.
41 */
42 #include "MagickCore/studio.h"
43 #include "MagickCore/blob.h"
44 #include "MagickCore/client.h"
45 #include "MagickCore/coder.h"
46 #include "MagickCore/coder-private.h"
47 #include "MagickCore/configure.h"
48 #include "MagickCore/draw.h"
49 #include "MagickCore/exception.h"
50 #include "MagickCore/exception-private.h"
51 #include "MagickCore/linked-list.h"
52 #include "MagickCore/log.h"
53 #include "MagickCore/memory_.h"
54 #include "MagickCore/option.h"
55 #include "MagickCore/semaphore.h"
56 #include "MagickCore/string_.h"
57 #include "MagickCore/splay-tree.h"
58 #include "MagickCore/token.h"
59 #include "MagickCore/utility.h"
60 #include "MagickCore/utility-private.h"
61 #include "MagickCore/xml-tree.h"
62 #include "MagickCore/xml-tree-private.h"
63 \f
64 /*
65   Define declarations.
66 */
67 #define MagickCoderFilename  "coder.xml"
68 \f
69 /*
70   Typedef declarations.
71 */
72 typedef struct _CoderMapInfo
73 {
74   const char
75     *magick,
76     *name;
77 } CoderMapInfo;
78 \f
79 /*
80   Static declarations.
81 */
82 static const CoderMapInfo
83   CoderMap[] =
84   {
85     { "3FR", "DNG" },
86     { "3GP", "MPEG" },
87     { "3G2", "MPEG" },
88     { "8BIMTEXT", "META" },
89     { "8BIMWTEXT", "META" },
90     { "AFM", "TTF" },
91     { "A", "RAW" },
92     { "AI", "PDF" },
93     { "APP1JPEG", "META" },
94     { "APP1", "META" },
95     { "ARW", "DNG" },
96     { "AVI", "MPEG" },
97     { "BIE", "JBIG" },
98     { "BMP2", "BMP" },
99     { "BMP3", "BMP" },
100     { "B", "RAW" },
101     { "BRF", "BRAILLE" },
102     { "BGRA", "BGR" },
103     { "BGRO", "BGR" },
104     { "CMYKA", "CMYK" },
105     { "C", "RAW" },
106     { "CAL", "CALS" },
107     { "CANVAS", "XC" },
108     { "CMYKA", "CMYK" },
109     { "CR2", "DNG" },
110     { "CRW", "DNG" },
111     { "CUR", "ICON" },
112     { "DATA", "INLINE" },
113     { "DCR", "DNG" },
114     { "DCX", "PCX" },
115     { "DFONT", "TTF" },
116     { "DXT1", "DDS" },
117     { "DXT5", "DDS" },
118     { "EPDF", "PDF" },
119     { "EPI", "PS" },
120     { "EPS2", "PS2" },
121     { "EPS3", "PS3" },
122     { "EPSF", "PS" },
123     { "EPSI", "PS" },
124     { "EPS", "PS" },
125     { "EPT2", "EPT" },
126     { "EPT3", "EPT" },
127     { "ERF", "DNG" },
128     { "EXIF", "META" },
129     { "FILE", "URL" },
130     { "FRACTAL", "PLASMA" },
131     { "FTP", "URL" },
132     { "FTS", "FITS" },
133     { "G3", "FAX" },
134     { "G4", "FAX" },
135     { "GIF87", "GIF" },
136     { "G", "RAW" },
137     { "GRANITE", "MAGICK" },
138     { "GROUP4", "TIFF" },
139     { "GV", "DOT" },
140     { "HTM", "HTML" },
141     { "ICB", "TGA" },
142     { "ICO", "ICON" },
143     { "IIQ", "DNG" },
144     { "K25", "DNG" },
145     { "KDC", "DNG" },
146     { "H", "MAGICK" },
147     { "HTM", "HTML" },
148     { "HTTP", "URL" },
149     { "HTTPS", "URL" },
150     { "ICB", "TGA" },
151     { "ICC", "META" },
152     { "ICM", "META" },
153     { "ICO", "ICON" },
154     { "IMPLICIT", "***" },
155     { "IPTC", "META" },
156     { "IPTCTEXT", "META" },
157     { "IPTCWTEXT", "META" },
158     { "ISOBRL", "BRAILLE" },
159     { "ISOBRL6", "BRAILLE" },
160     { "JBG", "JBIG" },
161     { "JNG", "PNG" },
162     { "JPC", "JP2" },
163     { "JPT", "JP2" },
164     { "JPM", "JP2" },
165     { "J2C", "JP2" },
166     { "J2K", "JP2" },
167     { "JNG", "PNG" },
168     { "JPE", "JPEG" },
169     { "JPG", "JPEG" },
170     { "JPM", "JP2" },
171     { "JPS", "JPEG" },
172     { "JPT", "JP2" },
173     { "JPX", "JP2" },
174     { "K", "RAW" },
175     { "K25", "DNG" },
176     { "KDC", "DNG" },
177     { "LOGO", "MAGICK" },
178     { "M", "RAW" },
179     { "M2V", "MPEG" },
180     { "M4V", "MPEG" },
181     { "MEF", "DNG" },
182     { "MKV", "MPEG" },
183     { "MNG", "PNG" },
184     { "MOV", "MPEG" },
185     { "MP4", "MPEG" },
186     { "MPG", "MPEG" },
187     { "MPRI", "MPR" },
188     { "MEF", "DNG" },
189     { "MRW", "DNG" },
190     { "MSVG", "SVG" },
191     { "NEF", "DNG" },
192     { "NETSCAPE", "MAGICK" },
193     { "NRW", "DNG" },
194     { "O", "RAW" },
195     { "ORF", "DNG" },
196     { "OTF", "TTF" },
197     { "P7", "PNM" },
198     { "PAL", "UYVY" },
199     { "PAM", "PNM" },
200     { "PBM", "PNM" },
201     { "PCDS", "PCD" },
202     { "PCT", "PICT" },
203     { "PDFA", "PDF" },
204     { "PEF", "DNG" },
205     { "PEF", "DNG" },
206     { "PFA", "TTF" },
207     { "PFB", "TTF" },
208     { "PFM", "PNM" },
209     { "PGM", "PNM" },
210     { "PGX", "JP2" },
211     { "PICON", "XPM" },
212     { "PJPEG", "JPEG" },
213     { "PM", "XPM" },
214     { "PNG00", "PNG" },
215     { "PNG24", "PNG" },
216     { "PNG32", "PNG" },
217     { "PNG48", "PNG" },
218     { "PNG64", "PNG" },
219     { "PNG8", "PNG" },
220     { "PPM", "PNM" },
221     { "PSB", "PSD" },
222     { "PTIF", "TIFF" },
223     { "R", "RAW" },
224     { "RADIAL-GRADIENT", "GRADIENT" },
225     { "RAF", "DNG" },
226     { "RAS", "SUN" },
227     { "RAW", "DNG" },
228     { "RGBA", "RGB" },
229     { "RGBO", "RGB" },
230     { "RMF", "DNG" },
231     { "ROSE", "MAGICK" },
232     { "RW2", "DNG" },
233     { "SHTML", "HTML" },
234     { "SIX", "SIXEL" },
235     { "SPARSE-COLOR", "TXT" },
236     { "SR2", "DNG" },
237     { "SRF", "DNG" },
238     { "SVGZ", "SVG" },
239     { "TEXT", "TXT" },
240     { "TIFF64", "TIFF" },
241     { "TIF", "TIFF" },
242     { "TTC", "TTF" },
243     { "UBRL", "BRAILLE" },
244     { "UBRL6", "BRAILLE" },
245     { "VDA", "TGA" },
246     { "VST", "TGA" },
247     { "WIZARD", "MAGICK" },
248 #if defined(MAGICKCORE_WINGDI32_DELEGATE)
249     { "WMF", "EMF" },
250 #endif
251     { "WMV", "MPEG" },
252     { "WMZ", "WMF" },
253     { "X3f", "DNG" },
254     { "XMP", "META" },
255     { "XTRNARRAY", "XTRN" },
256     { "XV", "VIFF" },
257     { "Y", "RAW" },
258     { "YCbCrA", "YCbCr" }
259  };
260
261 static SemaphoreInfo
262   *coder_semaphore = (SemaphoreInfo *) NULL;
263
264 static SplayTreeInfo
265   *coder_cache = (SplayTreeInfo *) NULL;
266 \f
267 /*
268   Forward declarations.
269 */
270 static MagickBooleanType
271   IsCoderTreeInstantiated(ExceptionInfo *),
272   LoadCoderCache(SplayTreeInfo *,const char *,const char *,const size_t,
273     ExceptionInfo *);
274 \f
275 /*
276 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
277 %                                                                             %
278 %                                                                             %
279 %                                                                             %
280 +  A c q u i r e C o d e r C a c h e                                          %
281 %                                                                             %
282 %                                                                             %
283 %                                                                             %
284 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
285 %
286 %  AcquireCoderCache() caches one or more coder configurations which provides a
287 %  mapping between coder attributes and a coder name.
288 %
289 %  The format of the AcquireCoderCache coder is:
290 %
291 %      SplayTreeInfo *AcquireCoderCache(const char *filename,
292 %        ExceptionInfo *exception)
293 %
294 %  A description of each parameter follows:
295 %
296 %    o filename: the font file name.
297 %
298 %    o exception: return any errors or warnings in this structure.
299 %
300 */
301
302 static void *DestroyCoderNode(void *coder_info)
303 {
304   register CoderInfo
305     *p;
306
307   p=(CoderInfo *) coder_info;
308   if (p->exempt == MagickFalse)
309     {
310       if (p->path != (char *) NULL)
311         p->path=DestroyString(p->path);
312       if (p->name != (char *) NULL)
313         p->name=DestroyString(p->name);
314       if (p->magick != (char *) NULL)
315         p->magick=DestroyString(p->magick);
316     }
317   return(RelinquishMagickMemory(p));
318 }
319
320 static SplayTreeInfo *AcquireCoderCache(const char *filename,
321   ExceptionInfo *exception)
322 {
323   MagickStatusType
324     status;
325
326   register ssize_t
327     i;
328
329   SplayTreeInfo
330     *cache;
331
332   /*
333     Load external coder map.
334   */
335   cache=NewSplayTree(CompareSplayTreeString,RelinquishMagickMemory,
336     DestroyCoderNode);
337   if (cache == (SplayTreeInfo *) NULL)
338     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
339   status=MagickTrue;
340 #if !defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
341   {
342     const StringInfo
343       *option;
344
345     LinkedListInfo
346       *options;
347
348     options=GetConfigureOptions(filename,exception);
349     option=(const StringInfo *) GetNextValueInLinkedList(options);
350     while (option != (const StringInfo *) NULL)
351     {
352       status&=LoadCoderCache(cache,(const char *) GetStringInfoDatum(option),
353         GetStringInfoPath(option),0,exception);
354       option=(const StringInfo *) GetNextValueInLinkedList(options);
355     }
356     options=DestroyConfigureOptions(options);
357   }
358 #endif
359   /*
360     Load built-in coder map.
361   */
362   for (i=0; i < (ssize_t) (sizeof(CoderMap)/sizeof(*CoderMap)); i++)
363   {
364     CoderInfo
365       *coder_info;
366
367     register const CoderMapInfo
368       *p;
369
370     p=CoderMap+i;
371     coder_info=(CoderInfo *) AcquireMagickMemory(sizeof(*coder_info));
372     if (coder_info == (CoderInfo *) NULL)
373       {
374         (void) ThrowMagickException(exception,GetMagickModule(),
375           ResourceLimitError,"MemoryAllocationFailed","`%s'",p->name);
376         continue;
377       }
378     (void) ResetMagickMemory(coder_info,0,sizeof(*coder_info));
379     coder_info->path=(char *) "[built-in]";
380     coder_info->magick=(char *) p->magick;
381     coder_info->name=(char *) p->name;
382     coder_info->exempt=MagickTrue;
383     coder_info->signature=MagickCoreSignature;
384     status&=AddValueToSplayTree(cache,ConstantString(coder_info->magick),
385       coder_info);
386     if (status == MagickFalse)
387       (void) ThrowMagickException(exception,GetMagickModule(),
388         ResourceLimitError,"MemoryAllocationFailed","`%s'",coder_info->name);
389   }
390   return(cache);
391 }
392 \f
393 /*
394 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
395 %                                                                             %
396 %                                                                             %
397 %                                                                             %
398 +   C o d e r C o m p o n e n t G e n e s i s                                 %
399 %                                                                             %
400 %                                                                             %
401 %                                                                             %
402 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
403 %
404 %  CoderComponentGenesis() instantiates the coder component.
405 %
406 %  The format of the CoderComponentGenesis method is:
407 %
408 %      MagickBooleanType CoderComponentGenesis(void)
409 %
410 */
411 MagickPrivate MagickBooleanType CoderComponentGenesis(void)
412 {
413   if (coder_semaphore == (SemaphoreInfo *) NULL)
414     coder_semaphore=AcquireSemaphoreInfo();
415   return(MagickTrue);
416 }
417 \f
418 /*
419 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
420 %                                                                             %
421 %                                                                             %
422 %                                                                             %
423 +   C o d e r C o m p o n e n t T e r m i n u s                               %
424 %                                                                             %
425 %                                                                             %
426 %                                                                             %
427 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
428 %
429 %  CoderComponentTerminus() destroys the coder component.
430 %
431 %  The format of the CoderComponentTerminus method is:
432 %
433 %      CoderComponentTerminus(void)
434 %
435 */
436 MagickPrivate void CoderComponentTerminus(void)
437 {
438   if (coder_semaphore == (SemaphoreInfo *) NULL)
439     ActivateSemaphoreInfo(&coder_semaphore);
440   LockSemaphoreInfo(coder_semaphore);
441   if (coder_cache != (SplayTreeInfo *) NULL)
442     coder_cache=DestroySplayTree(coder_cache);
443   UnlockSemaphoreInfo(coder_semaphore);
444   RelinquishSemaphoreInfo(&coder_semaphore);
445 }
446 \f
447 /*
448 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
449 %                                                                             %
450 %                                                                             %
451 %                                                                             %
452 +   G e t C o d e r I n f o                                                   %
453 %                                                                             %
454 %                                                                             %
455 %                                                                             %
456 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
457 %
458 %  GetCoderInfo searches the coder list for the specified name and if found
459 %  returns attributes for that coder.
460 %
461 %  The format of the GetCoderInfo method is:
462 %
463 %      const CoderInfo *GetCoderInfo(const char *name,ExceptionInfo *exception)
464 %
465 %  A description of each parameter follows:
466 %
467 %    o name: the coder name.
468 %
469 %    o exception: return any errors or warnings in this structure.
470 %
471 */
472 MagickExport const CoderInfo *GetCoderInfo(const char *name,
473   ExceptionInfo *exception)
474 {
475   const CoderInfo
476     *coder_info;
477
478   assert(exception != (ExceptionInfo *) NULL);
479   if (IsCoderTreeInstantiated(exception) == MagickFalse)
480     return((const CoderInfo *) NULL);
481   LockSemaphoreInfo(coder_semaphore);
482   if ((name == (const char *) NULL) || (LocaleCompare(name,"*") == 0))
483     {
484       ResetSplayTreeIterator(coder_cache);
485       coder_info=(const CoderInfo *) GetNextValueInSplayTree(coder_cache);
486       UnlockSemaphoreInfo(coder_semaphore);
487       return(coder_info);
488     }
489   coder_info=(const CoderInfo *) GetValueFromSplayTree(coder_cache,name);
490   UnlockSemaphoreInfo(coder_semaphore);
491   return(coder_info);
492 }
493 \f
494 /*
495 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
496 %                                                                             %
497 %                                                                             %
498 %                                                                             %
499 %   G e t C o d e r I n f o L i s t                                           %
500 %                                                                             %
501 %                                                                             %
502 %                                                                             %
503 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
504 %
505 %  GetCoderInfoList() returns any coder_map that match the specified pattern.
506 %  The format of the GetCoderInfoList function is:
507 %
508 %      const CoderInfo **GetCoderInfoList(const char *pattern,
509 %        size_t *number_coders,ExceptionInfo *exception)
510 %
511 %  A description of each parameter follows:
512 %
513 %    o pattern: Specifies a pointer to a text string containing a pattern.
514 %
515 %    o number_coders:  This integer returns the number of coders in the list.
516 %
517 %    o exception: return any errors or warnings in this structure.
518 %
519 */
520
521 static int CoderInfoCompare(const void *x,const void *y)
522 {
523   const CoderInfo
524     **p,
525     **q;
526
527   p=(const CoderInfo **) x,
528   q=(const CoderInfo **) y;
529   if (LocaleCompare((*p)->path,(*q)->path) == 0)
530     return(LocaleCompare((*p)->name,(*q)->name));
531   return(LocaleCompare((*p)->path,(*q)->path));
532 }
533
534 MagickExport const CoderInfo **GetCoderInfoList(const char *pattern,
535   size_t *number_coders,ExceptionInfo *exception)
536 {
537   const CoderInfo
538     **coder_map;
539
540   register const CoderInfo
541     *p;
542
543   register ssize_t
544     i;
545
546   /*
547     Allocate coder list.
548   */
549   assert(pattern != (char *) NULL);
550   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
551   assert(number_coders != (size_t *) NULL);
552   *number_coders=0;
553   p=GetCoderInfo("*",exception);
554   if (p == (const CoderInfo *) NULL)
555     return((const CoderInfo **) NULL);
556   coder_map=(const CoderInfo **) AcquireQuantumMemory((size_t)
557     GetNumberOfNodesInSplayTree(coder_cache)+1UL,sizeof(*coder_map));
558   if (coder_map == (const CoderInfo **) NULL)
559     return((const CoderInfo **) NULL);
560   /*
561     Generate coder list.
562   */
563   LockSemaphoreInfo(coder_semaphore);
564   ResetSplayTreeIterator(coder_cache);
565   p=(const CoderInfo *) GetNextValueInSplayTree(coder_cache);
566   for (i=0; p != (const CoderInfo *) NULL; )
567   {
568     if ((p->stealth == MagickFalse) &&
569         (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
570       coder_map[i++]=p;
571     p=(const CoderInfo *) GetNextValueInSplayTree(coder_cache);
572   }
573   UnlockSemaphoreInfo(coder_semaphore);
574   qsort((void *) coder_map,(size_t) i,sizeof(*coder_map),CoderInfoCompare);
575   coder_map[i]=(CoderInfo *) NULL;
576   *number_coders=(size_t) i;
577   return(coder_map);
578 }
579 \f
580 /*
581 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
582 %                                                                             %
583 %                                                                             %
584 %                                                                             %
585 %   G e t C o d e r L i s t                                                   %
586 %                                                                             %
587 %                                                                             %
588 %                                                                             %
589 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
590 %
591 %  GetCoderList() returns any coder_map that match the specified pattern.
592 %
593 %  The format of the GetCoderList function is:
594 %
595 %      char **GetCoderList(const char *pattern,size_t *number_coders,
596 %        ExceptionInfo *exception)
597 %
598 %  A description of each parameter follows:
599 %
600 %    o pattern: Specifies a pointer to a text string containing a pattern.
601 %
602 %    o number_coders:  This integer returns the number of coders in the list.
603 %
604 %    o exception: return any errors or warnings in this structure.
605 %
606 */
607
608 static int CoderCompare(const void *x,const void *y)
609 {
610   register const char
611     **p,
612     **q;
613
614   p=(const char **) x;
615   q=(const char **) y;
616   return(LocaleCompare(*p,*q));
617 }
618
619 MagickExport char **GetCoderList(const char *pattern,
620   size_t *number_coders,ExceptionInfo *exception)
621 {
622   char
623     **coder_map;
624
625   register const CoderInfo
626     *p;
627
628   register ssize_t
629     i;
630
631   /*
632     Allocate coder list.
633   */
634   assert(pattern != (char *) NULL);
635   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
636   assert(number_coders != (size_t *) NULL);
637   *number_coders=0;
638   p=GetCoderInfo("*",exception);
639   if (p == (const CoderInfo *) NULL)
640     return((char **) NULL);
641   coder_map=(char **) AcquireQuantumMemory((size_t)
642     GetNumberOfNodesInSplayTree(coder_cache)+1UL,sizeof(*coder_map));
643   if (coder_map == (char **) NULL)
644     return((char **) NULL);
645   /*
646     Generate coder list.
647   */
648   LockSemaphoreInfo(coder_semaphore);
649   ResetSplayTreeIterator(coder_cache);
650   p=(const CoderInfo *) GetNextValueInSplayTree(coder_cache);
651   for (i=0; p != (const CoderInfo *) NULL; )
652   {
653     if ((p->stealth == MagickFalse) &&
654         (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
655       coder_map[i++]=ConstantString(p->name);
656     p=(const CoderInfo *) GetNextValueInSplayTree(coder_cache);
657   }
658   UnlockSemaphoreInfo(coder_semaphore);
659   qsort((void *) coder_map,(size_t) i,sizeof(*coder_map),CoderCompare);
660   coder_map[i]=(char *) NULL;
661   *number_coders=(size_t) i;
662   return(coder_map);
663 }
664 \f
665 /*
666 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
667 %                                                                             %
668 %                                                                             %
669 %                                                                             %
670 +   I s C o d e r T r e e I n s t a n t i a t e d                             %
671 %                                                                             %
672 %                                                                             %
673 %                                                                             %
674 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
675 %
676 %  IsCoderTreeInstantiated() determines if the coder tree is instantiated.  If
677 %  not, it instantiates the tree and returns it.
678 %
679 %  The format of the IsCoderInstantiated method is:
680 %
681 %      MagickBooleanType IsCoderTreeInstantiated(ExceptionInfo *exception)
682 %
683 %  A description of each parameter follows.
684 %
685 %    o exception: return any errors or warnings in this structure.
686 %
687 */
688 static MagickBooleanType IsCoderTreeInstantiated(ExceptionInfo *exception)
689 {
690   if (coder_cache == (SplayTreeInfo *) NULL)
691     {
692       if (coder_semaphore == (SemaphoreInfo *) NULL)
693         ActivateSemaphoreInfo(&coder_semaphore);
694       LockSemaphoreInfo(coder_semaphore);
695       if (coder_cache == (SplayTreeInfo *) NULL)
696         coder_cache=AcquireCoderCache(MagickCoderFilename,exception);
697       UnlockSemaphoreInfo(coder_semaphore);
698     }
699   return(coder_cache != (SplayTreeInfo *) NULL ? MagickTrue : MagickFalse);
700 }
701 \f
702 /*
703 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
704 %                                                                             %
705 %                                                                             %
706 %                                                                             %
707 %  L i s t C o d e r I n f o                                                  %
708 %                                                                             %
709 %                                                                             %
710 %                                                                             %
711 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
712 %
713 %  ListCoderInfo() lists the coder info to a file.
714 %
715 %  The format of the ListCoderInfo coder is:
716 %
717 %      MagickBooleanType ListCoderInfo(FILE *file,ExceptionInfo *exception)
718 %
719 %  A description of each parameter follows.
720 %
721 %    o file:  An pointer to a FILE.
722 %
723 %    o exception: return any errors or warnings in this structure.
724 %
725 */
726 MagickExport MagickBooleanType ListCoderInfo(FILE *file,
727   ExceptionInfo *exception)
728 {
729   const char
730     *path;
731
732   const CoderInfo
733     **coder_info;
734
735   register ssize_t
736     i;
737
738   size_t
739     number_coders;
740
741   ssize_t
742     j;
743
744   if (file == (const FILE *) NULL)
745     file=stdout;
746   coder_info=GetCoderInfoList("*",&number_coders,exception);
747   if (coder_info == (const CoderInfo **) NULL)
748     return(MagickFalse);
749   path=(const char *) NULL;
750   for (i=0; i < (ssize_t) number_coders; i++)
751   {
752     if (coder_info[i]->stealth != MagickFalse)
753       continue;
754     if ((path == (const char *) NULL) ||
755         (LocaleCompare(path,coder_info[i]->path) != 0))
756       {
757         if (coder_info[i]->path != (char *) NULL)
758           (void) FormatLocaleFile(file,"\nPath: %s\n\n",coder_info[i]->path);
759         (void) FormatLocaleFile(file,"Magick      Coder\n");
760         (void) FormatLocaleFile(file,
761           "-------------------------------------------------"
762           "------------------------------\n");
763       }
764     path=coder_info[i]->path;
765     (void) FormatLocaleFile(file,"%s",coder_info[i]->magick);
766     for (j=(ssize_t) strlen(coder_info[i]->magick); j <= 11; j++)
767       (void) FormatLocaleFile(file," ");
768     if (coder_info[i]->name != (char *) NULL)
769       (void) FormatLocaleFile(file,"%s",coder_info[i]->name);
770     (void) FormatLocaleFile(file,"\n");
771   }
772   coder_info=(const CoderInfo **) RelinquishMagickMemory((void *) coder_info);
773   (void) fflush(file);
774   return(MagickTrue);
775 }
776 \f
777 /*
778 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
779 %                                                                             %
780 %                                                                             %
781 %                                                                             %
782 +   L o a d C o d e r C a c h e                                               %
783 %                                                                             %
784 %                                                                             %
785 %                                                                             %
786 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
787 %
788 %  LoadCoderCache() loads the coder configurations which provides a
789 %  mapping between coder attributes and a coder name.
790 %
791 %  The format of the LoadCoderCache coder is:
792 %
793 %      MagickBooleanType LoadCoderCache(SplayTreeInfo *cache,const char *xml,
794 %        const char *filename,const size_t depth,ExceptionInfo *exception)
795 %
796 %  A description of each parameter follows:
797 %
798 %    o xml:  The coder list in XML format.
799 %
800 %    o filename:  The coder list filename.
801 %
802 %    o depth: depth of <include /> statements.
803 %
804 %    o exception: return any errors or warnings in this structure.
805 %
806 */
807 static MagickBooleanType LoadCoderCache(SplayTreeInfo *cache,const char *xml,
808   const char *filename,const size_t depth,ExceptionInfo *exception)
809 {
810   char
811     keyword[MagickPathExtent],
812     *token;
813
814   const char
815     *q;
816
817   CoderInfo
818     *coder_info;
819
820   MagickStatusType
821     status;
822
823   size_t
824     extent;
825
826   /*
827     Load the coder map file.
828   */
829   (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
830     "Loading coder configuration file \"%s\" ...",filename);
831   if (xml == (const char *) NULL)
832     return(MagickFalse);
833   status=MagickTrue;
834   coder_info=(CoderInfo *) NULL;
835   token=AcquireString(xml);
836   extent=strlen(token)+MagickPathExtent;
837   for (q=(char *) xml; *q != '\0'; )
838   {
839     /*
840       Interpret XML.
841     */
842     GetNextToken(q,&q,extent,token);
843     if (*token == '\0')
844       break;
845     (void) CopyMagickString(keyword,token,MagickPathExtent);
846     if (LocaleNCompare(keyword,"<!DOCTYPE",9) == 0)
847       {
848         /*
849           Doctype element.
850         */
851         while ((LocaleNCompare(q,"]>",2) != 0) && (*q != '\0'))
852           GetNextToken(q,&q,extent,token);
853         continue;
854       }
855     if (LocaleNCompare(keyword,"<!--",4) == 0)
856       {
857         /*
858           Comment element.
859         */
860         while ((LocaleNCompare(q,"->",2) != 0) && (*q != '\0'))
861           GetNextToken(q,&q,extent,token);
862         continue;
863       }
864     if (LocaleCompare(keyword,"<include") == 0)
865       {
866         /*
867           Include element.
868         */
869         while (((*token != '/') && (*(token+1) != '>')) && (*q != '\0'))
870         {
871           (void) CopyMagickString(keyword,token,MagickPathExtent);
872           GetNextToken(q,&q,extent,token);
873           if (*token != '=')
874             continue;
875           GetNextToken(q,&q,extent,token);
876           if (LocaleCompare(keyword,"file") == 0)
877             {
878               if (depth > 200)
879                 (void) ThrowMagickException(exception,GetMagickModule(),
880                   ConfigureError,"IncludeNodeNestedTooDeeply","`%s'",token);
881               else
882                 {
883                   char
884                     path[MagickPathExtent],
885                     *file_xml;
886
887                   GetPathComponent(filename,HeadPath,path);
888                   if (*path != '\0')
889                     (void) ConcatenateMagickString(path,DirectorySeparator,
890                       MagickPathExtent);
891                   if (*token == *DirectorySeparator)
892                     (void) CopyMagickString(path,token,MagickPathExtent);
893                   else
894                     (void) ConcatenateMagickString(path,token,MagickPathExtent);
895                   file_xml=FileToXML(path,~0UL);
896                   if (file_xml != (char *) NULL)
897                     {
898                       status&=LoadCoderCache(cache,file_xml,path,depth+1,
899                         exception);
900                       file_xml=DestroyString(file_xml);
901                     }
902                 }
903             }
904         }
905         continue;
906       }
907     if (LocaleCompare(keyword,"<coder") == 0)
908       {
909         /*
910           Coder element.
911         */
912         coder_info=(CoderInfo *) AcquireMagickMemory(sizeof(*coder_info));
913         if (coder_info == (CoderInfo *) NULL)
914           ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
915         (void) ResetMagickMemory(coder_info,0,sizeof(*coder_info));
916         coder_info->path=ConstantString(filename);
917         coder_info->exempt=MagickFalse;
918         coder_info->signature=MagickCoreSignature;
919         continue;
920       }
921     if (coder_info == (CoderInfo *) NULL)
922       continue;
923     if ((LocaleCompare(keyword,"/>") == 0) ||
924         (LocaleCompare(keyword,"</policy>") == 0))
925       {
926         status=AddValueToSplayTree(cache,ConstantString(coder_info->magick),
927           coder_info);
928         if (status == MagickFalse)
929           (void) ThrowMagickException(exception,GetMagickModule(),
930             ResourceLimitError,"MemoryAllocationFailed","`%s'",
931             coder_info->magick);
932         coder_info=(CoderInfo *) NULL;
933         continue;
934       }
935     GetNextToken(q,(const char **) NULL,extent,token);
936     if (*token != '=')
937       continue;
938     GetNextToken(q,&q,extent,token);
939     GetNextToken(q,&q,extent,token);
940     switch (*keyword)
941     {
942       case 'M':
943       case 'm':
944       {
945         if (LocaleCompare((char *) keyword,"magick") == 0)
946           {
947             coder_info->magick=ConstantString(token);
948             break;
949           }
950         break;
951       }
952       case 'N':
953       case 'n':
954       {
955         if (LocaleCompare((char *) keyword,"name") == 0)
956           {
957             coder_info->name=ConstantString(token);
958             break;
959           }
960         break;
961       }
962       case 'S':
963       case 's':
964       {
965         if (LocaleCompare((char *) keyword,"stealth") == 0)
966           {
967             coder_info->stealth=IsStringTrue(token);
968             break;
969           }
970         break;
971       }
972       default:
973         break;
974     }
975   }
976   token=(char *) RelinquishMagickMemory(token);
977   return(status != 0 ? MagickTrue : MagickFalse);
978 }