]> granicus.if.org Git - imagemagick/blob - MagickCore/configure.c
Support Stereo composite operator
[imagemagick] / MagickCore / configure.c
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 %                                                                             %
4 %                                                                             %
5 %                                                                             %
6 %          CCCC   OOO   N   N  FFFFF  IIIII   GGGG  U   U  RRRR   EEEEE       %
7 %         C      O   O  NN  N  F        I    G      U   U  R   R  E           %
8 %         C      O   O  N N N  FFF      I    G GG   U   U  RRRR   EEE         %
9 %         C      O   O  N  NN  F        I    G   G  U   U  R R    E           %
10 %          CCCC   OOO   N   N  F      IIIII   GGG    UUU   R  R   EEEEE       %
11 %                                                                             %
12 %                                                                             %
13 %                      MagickCore Image Configure Methods                     %
14 %                                                                             %
15 %                              Software Design                                %
16 %                                   Cristy                                    %
17 %                                 July 2003                                   %
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/configure.h"
46 #include "MagickCore/configure-private.h"
47 #include "MagickCore/exception.h"
48 #include "MagickCore/exception-private.h"
49 #include "MagickCore/linked-list.h"
50 #include "MagickCore/log.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/string-private.h"
56 #include "MagickCore/token.h"
57 #include "MagickCore/utility.h"
58 #include "MagickCore/utility-private.h"
59 #include "MagickCore/xml-tree.h"
60 #include "MagickCore/xml-tree-private.h"
61 \f
62 /*
63   Define declarations.
64 */
65 #define ConfigureFilename  "configure.xml"
66
67 #ifdef _OPENMP
68 #define MAGICKCORE_FEATURE_OPENMP_STR "OpenMP "
69 #else
70 #define MAGICKCORE_FEATURE_OPENMP_STR ""
71 #endif
72 #ifdef _OPENCL
73 #define MAGICKCORE_FEATURE_OPENCL_STR "OpenCL "
74 #else
75 #define MAGICKCORE_FEATURE_OPENCL_STR ""
76 #endif
77 #ifdef MAGICKCORE_ZERO_CONFIGURATION_SUPPORT
78 #define MAGICKCORE_FEATURE_ZERO_CONFIGURATION_STR "Zero-Configuration "
79 #else
80 #define MAGICKCORE_FEATURE_ZERO_CONFIGURATION_STR ""
81 #endif
82 #ifdef HDRI_SUPPORT
83 #define MAGICKCORE_FEATURE_HDRI_STR "HDRI"
84 #else
85 #define MAGICKCORE_FEATURE_HDRI_STR ""
86 #endif
87
88 #define MAGICKCORE_FEATURES_STR MAGICKCORE_FEATURE_OPENMP_STR MAGICKCORE_FEATURE_OPENCL_STR MAGICKCORE_FEATURE_ZERO_CONFIGURATION_STR MAGICKCORE_FEATURE_HDRI_STR
89 \f
90 /*
91   Typedef declarations.
92 */
93 typedef struct _ConfigureMapInfo
94 {
95   const char
96     *name,
97     *value;
98 } ConfigureMapInfo;
99 \f
100 /*
101   Static declarations.
102 */
103 static const ConfigureMapInfo
104   ConfigureMap[] =
105   {
106     { "NAME", "ImageMagick" },
107     { "QuantumDepth", MAGICKCORE_STRING_XQUOTE(MAGICKCORE_QUANTUM_DEPTH) } ,
108     { "FEATURES", MAGICKCORE_FEATURES_STR }
109   };
110
111 static LinkedListInfo
112   *configure_cache = (LinkedListInfo *) NULL;
113
114 static SemaphoreInfo
115   *configure_semaphore = (SemaphoreInfo *) NULL;
116 \f
117 /*
118   Forward declarations.
119 */
120 static MagickBooleanType
121   IsConfigureCacheInstantiated(ExceptionInfo *),
122   LoadConfigureCache(LinkedListInfo *,const char *,const char *,const size_t,
123     ExceptionInfo *);
124 \f
125 /*
126 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
127 %                                                                             %
128 %                                                                             %
129 %                                                                             %
130 %  A c q u i r e C o n f i g u r e C a c h e                                  %
131 %                                                                             %
132 %                                                                             %
133 %                                                                             %
134 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
135 %
136 %  AcquireConfigureCache() caches one or more configure configurations which
137 %  provides a mapping between configure attributes and a configure name.
138 %
139 %  The format of the AcquireConfigureCache method is:
140 %
141 %      LinkedListInfo *AcquireConfigureCache(const char *filename,
142 %        ExceptionInfo *exception)
143 %
144 %  A description of each parameter follows:
145 %
146 %    o filename: the font file name.
147 %
148 %    o exception: return any errors or warnings in this structure.
149 %
150 */
151 static LinkedListInfo *AcquireConfigureCache(const char *filename,
152   ExceptionInfo *exception)
153 {
154   LinkedListInfo
155     *cache;
156
157   MagickStatusType
158     status;
159
160   register ssize_t
161     i;
162
163   /*
164     Load external configure map.
165   */
166   cache=NewLinkedList(0);
167   status=MagickTrue;
168 #if !defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
169   {
170     const StringInfo
171       *option;
172
173     LinkedListInfo
174       *options;
175
176     options=GetConfigureOptions(filename,exception);
177     option=(const StringInfo *) GetNextValueInLinkedList(options);
178     while (option != (const StringInfo *) NULL)
179     {
180       status&=LoadConfigureCache(cache,(const char *)
181         GetStringInfoDatum(option),GetStringInfoPath(option),0,exception);
182       option=(const StringInfo *) GetNextValueInLinkedList(options);
183     }
184     options=DestroyConfigureOptions(options);
185   }
186 #endif
187   /*
188     Load built-in configure map.
189   */
190   for (i=0; i < (ssize_t) (sizeof(ConfigureMap)/sizeof(*ConfigureMap)); i++)
191   {
192     ConfigureInfo
193       *configure_info;
194
195     register const ConfigureMapInfo
196       *p;
197
198     p=ConfigureMap+i;
199     configure_info=(ConfigureInfo *) AcquireMagickMemory(
200       sizeof(*configure_info));
201     if (configure_info == (ConfigureInfo *) NULL)
202       {
203         (void) ThrowMagickException(exception,GetMagickModule(),
204           ResourceLimitError,"MemoryAllocationFailed","`%s'",p->name);
205         continue;
206       }
207     (void) ResetMagickMemory(configure_info,0,sizeof(*configure_info));
208     configure_info->path=(char *) "[built-in]";
209     configure_info->name=(char *) p->name;
210     configure_info->value=(char *) p->value;
211     configure_info->exempt=MagickTrue;
212     configure_info->signature=MagickCoreSignature;
213     status&=AppendValueToLinkedList(cache,configure_info);
214     if (status == MagickFalse)
215       (void) ThrowMagickException(exception,GetMagickModule(),
216         ResourceLimitError,"MemoryAllocationFailed","`%s'",
217         configure_info->name);
218   }
219   return(cache);
220 }
221 \f
222 /*
223 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
224 %                                                                             %
225 %                                                                             %
226 %                                                                             %
227 +   C o n f i g u r e C o m p o n e n t G e n e s i s                         %
228 %                                                                             %
229 %                                                                             %
230 %                                                                             %
231 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
232 %
233 %  ConfigureComponentGenesis() instantiates the configure component.
234 %
235 %  The format of the ConfigureComponentGenesis method is:
236 %
237 %      MagickBooleanType ConfigureComponentGenesis(void)
238 %
239 */
240 MagickPrivate MagickBooleanType ConfigureComponentGenesis(void)
241 {
242   if (configure_semaphore == (SemaphoreInfo *) NULL)
243     configure_semaphore=AcquireSemaphoreInfo();
244   return(MagickTrue);
245 }
246 \f
247 /*
248 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
249 %                                                                             %
250 %                                                                             %
251 %                                                                             %
252 +   C o n f i g u r e C o m p o n e n t T e r m i n u s                       %
253 %                                                                             %
254 %                                                                             %
255 %                                                                             %
256 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
257 %
258 %  ConfigureComponentTerminus() destroys the configure component.
259 %
260 %  The format of the ConfigureComponentTerminus method is:
261 %
262 %      ConfigureComponentTerminus(void)
263 %
264 */
265
266 static void *DestroyConfigureElement(void *configure_info)
267 {
268   register ConfigureInfo
269     *p;
270
271   p=(ConfigureInfo *) configure_info;
272   if (p->exempt == MagickFalse)
273     {
274       if (p->value != (char *) NULL)
275         p->value=DestroyString(p->value);
276       if (p->name != (char *) NULL)
277         p->name=DestroyString(p->name);
278       if (p->path != (char *) NULL)
279         p->path=DestroyString(p->path);
280     }
281   p=(ConfigureInfo *) RelinquishMagickMemory(p);
282   return((void *) NULL);
283 }
284
285 MagickPrivate void ConfigureComponentTerminus(void)
286 {
287   if (configure_semaphore == (SemaphoreInfo *) NULL)
288     ActivateSemaphoreInfo(&configure_semaphore);
289   LockSemaphoreInfo(configure_semaphore);
290   if (configure_cache != (LinkedListInfo *) NULL)
291     configure_cache=DestroyLinkedList(configure_cache,DestroyConfigureElement);
292   configure_cache=(LinkedListInfo *) NULL;
293   UnlockSemaphoreInfo(configure_semaphore);
294   RelinquishSemaphoreInfo(&configure_semaphore);
295 }
296 \f
297 /*
298 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
299 %                                                                             %
300 %                                                                             %
301 %                                                                             %
302 %   D e s t r o y C o n f i g u r e O p t i o n s                             %
303 %                                                                             %
304 %                                                                             %
305 %                                                                             %
306 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
307 %
308 %  DestroyConfigureOptions() releases memory associated with an configure
309 %  options.
310 %
311 %  The format of the DestroyProfiles method is:
312 %
313 %      LinkedListInfo *DestroyConfigureOptions(Image *image)
314 %
315 %  A description of each parameter follows:
316 %
317 %    o image: the image.
318 %
319 */
320
321 static void *DestroyOptions(void *option)
322 {
323   return(DestroyStringInfo((StringInfo *) option));
324 }
325
326 MagickExport LinkedListInfo *DestroyConfigureOptions(LinkedListInfo *options)
327 {
328   assert(options != (LinkedListInfo *) NULL);
329   return(DestroyLinkedList(options,DestroyOptions));
330 }
331 \f
332 /*
333 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
334 %                                                                             %
335 %                                                                             %
336 %                                                                             %
337 +   G e t C o n f i g u r e I n f o                                           %
338 %                                                                             %
339 %                                                                             %
340 %                                                                             %
341 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
342 %
343 %  GetConfigureInfo() searches the configure list for the specified name and if
344 %  found returns attributes for that element.
345 %
346 %  The format of the GetConfigureInfo method is:
347 %
348 %      const ConfigureInfo *GetConfigureInfo(const char *name,
349 %        ExceptionInfo *exception)
350 %
351 %  A description of each parameter follows:
352 %
353 %    o configure_info: GetConfigureInfo() searches the configure list for the
354 %      specified name and if found returns attributes for that element.
355 %
356 %    o name: the configure name.
357 %
358 %    o exception: return any errors or warnings in this structure.
359 %
360 */
361 MagickExport const ConfigureInfo *GetConfigureInfo(const char *name,
362   ExceptionInfo *exception)
363 {
364   register const ConfigureInfo
365     *p;
366
367   assert(exception != (ExceptionInfo *) NULL);
368   if (IsConfigureCacheInstantiated(exception) == MagickFalse)
369     return((const ConfigureInfo *) NULL);
370   /*
371     Search for configure tag.
372   */
373   LockSemaphoreInfo(configure_semaphore);
374   ResetLinkedListIterator(configure_cache);
375   p=(const ConfigureInfo *) GetNextValueInLinkedList(configure_cache);
376   if ((name == (const char *) NULL) || (LocaleCompare(name,"*") == 0))
377     {
378       UnlockSemaphoreInfo(configure_semaphore);
379       return(p);
380     }
381   while (p != (const ConfigureInfo *) NULL)
382   {
383     if (LocaleCompare(name,p->name) == 0)
384       break;
385     p=(const ConfigureInfo *) GetNextValueInLinkedList(configure_cache);
386   }
387   if (p != (ConfigureInfo *) NULL)
388     (void) InsertValueInLinkedList(configure_cache,0,
389       RemoveElementByValueFromLinkedList(configure_cache,p));
390   UnlockSemaphoreInfo(configure_semaphore);
391   return(p);
392 }
393 \f
394 /*
395 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
396 %                                                                             %
397 %                                                                             %
398 %                                                                             %
399 %   G e t C o n f i g u r e I n f o L i s t                                   %
400 %                                                                             %
401 %                                                                             %
402 %                                                                             %
403 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
404 %
405 %  GetConfigureInfoList() returns any configure options that match the
406 %  specified pattern.
407 %
408 %  The format of the GetConfigureInfoList function is:
409 %
410 %      const ConfigureInfo **GetConfigureInfoList(const char *pattern,
411 %        size_t *number_options,ExceptionInfo *exception)
412 %
413 %  A description of each parameter follows:
414 %
415 %    o pattern: Specifies a pointer to a text string containing a pattern.
416 %
417 %    o number_options:  This integer returns the number of configure options in
418 %    the list.
419 %
420 %    o exception: return any errors or warnings in this structure.
421 %
422 */
423
424 #if defined(__cplusplus) || defined(c_plusplus)
425 extern "C" {
426 #endif
427
428 static int ConfigureInfoCompare(const void *x,const void *y)
429 {
430   const ConfigureInfo
431     **p,
432     **q;
433
434   p=(const ConfigureInfo **) x,
435   q=(const ConfigureInfo **) y;
436   if (LocaleCompare((*p)->path,(*q)->path) == 0)
437     return(LocaleCompare((*p)->name,(*q)->name));
438   return(LocaleCompare((*p)->path,(*q)->path));
439 }
440
441 #if defined(__cplusplus) || defined(c_plusplus)
442 }
443 #endif
444
445 MagickExport const ConfigureInfo **GetConfigureInfoList(const char *pattern,
446   size_t *number_options,ExceptionInfo *exception)
447 {
448   const ConfigureInfo
449     **options;
450
451   register const ConfigureInfo
452     *p;
453
454   register ssize_t
455     i;
456
457   /*
458     Allocate configure list.
459   */
460   assert(pattern != (char *) NULL);
461   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
462   assert(number_options != (size_t *) NULL);
463   *number_options=0;
464   p=GetConfigureInfo("*",exception);
465   if (p == (const ConfigureInfo *) NULL)
466     return((const ConfigureInfo **) NULL);
467   options=(const ConfigureInfo **) AcquireQuantumMemory((size_t)
468     GetNumberOfElementsInLinkedList(configure_cache)+1UL,sizeof(*options));
469   if (options == (const ConfigureInfo **) NULL)
470     return((const ConfigureInfo **) NULL);
471   /*
472     Generate configure list.
473   */
474   LockSemaphoreInfo(configure_semaphore);
475   ResetLinkedListIterator(configure_cache);
476   p=(const ConfigureInfo *) GetNextValueInLinkedList(configure_cache);
477   for (i=0; p != (const ConfigureInfo *) NULL; )
478   {
479     if ((p->stealth == MagickFalse) &&
480         (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
481       options[i++]=p;
482     p=(const ConfigureInfo *) GetNextValueInLinkedList(configure_cache);
483   }
484   UnlockSemaphoreInfo(configure_semaphore);
485   qsort((void *) options,(size_t) i,sizeof(*options),ConfigureInfoCompare);
486   options[i]=(ConfigureInfo *) NULL;
487   *number_options=(size_t) i;
488   return(options);
489 }
490 \f
491 /*
492 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
493 %                                                                             %
494 %                                                                             %
495 %                                                                             %
496 %   G e t C o n f i g u r e L i s t                                           %
497 %                                                                             %
498 %                                                                             %
499 %                                                                             %
500 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
501 %
502 %  GetConfigureList() returns any configure options that match the specified
503 %  pattern.
504 %
505 %  The format of the GetConfigureList function is:
506 %
507 %      char **GetConfigureList(const char *pattern,
508 %        size_t *number_options,ExceptionInfo *exception)
509 %
510 %  A description of each parameter follows:
511 %
512 %    o pattern: Specifies a pointer to a text string containing a pattern.
513 %
514 %    o number_options:  This integer returns the number of options in the list.
515 %
516 %    o exception: return any errors or warnings in this structure.
517 %
518 */
519
520 #if defined(__cplusplus) || defined(c_plusplus)
521 extern "C" {
522 #endif
523
524 static int ConfigureCompare(const void *x,const void *y)
525 {
526   register char
527     **p,
528     **q;
529
530   p=(char **) x;
531   q=(char **) y;
532   return(LocaleCompare(*p,*q));
533 }
534
535 #if defined(__cplusplus) || defined(c_plusplus)
536 }
537 #endif
538
539 MagickExport char **GetConfigureList(const char *pattern,
540   size_t *number_options,ExceptionInfo *exception)
541 {
542   char
543     **options;
544
545   register const ConfigureInfo
546     *p;
547
548   register ssize_t
549     i;
550
551   /*
552     Allocate configure list.
553   */
554   assert(pattern != (char *) NULL);
555   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
556   assert(number_options != (size_t *) NULL);
557   *number_options=0;
558   p=GetConfigureInfo("*",exception);
559   if (p == (const ConfigureInfo *) NULL)
560     return((char **) NULL);
561   options=(char **) AcquireQuantumMemory((size_t)
562     GetNumberOfElementsInLinkedList(configure_cache)+1UL,sizeof(*options));
563   if (options == (char **) NULL)
564     return((char **) NULL);
565   LockSemaphoreInfo(configure_semaphore);
566   ResetLinkedListIterator(configure_cache);
567   p=(const ConfigureInfo *) GetNextValueInLinkedList(configure_cache);
568   for (i=0; p != (const ConfigureInfo *) NULL; )
569   {
570     if ((p->stealth == MagickFalse) &&
571         (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
572       options[i++]=ConstantString(p->name);
573     p=(const ConfigureInfo *) GetNextValueInLinkedList(configure_cache);
574   }
575   UnlockSemaphoreInfo(configure_semaphore);
576   qsort((void *) options,(size_t) i,sizeof(*options),ConfigureCompare);
577   options[i]=(char *) NULL;
578   *number_options=(size_t) i;
579   return(options);
580 }
581 \f
582 /*
583 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
584 %                                                                             %
585 %                                                                             %
586 %                                                                             %
587 %   G e t C o n f i g u r e O p t i o n                                       %
588 %                                                                             %
589 %                                                                             %
590 %                                                                             %
591 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
592 %
593 %  GetConfigureOption() returns the value associated with the configure option.
594 %
595 %  The format of the GetConfigureOption method is:
596 %
597 %      char *GetConfigureOption(const char *option)
598 %
599 %  A description of each parameter follows:
600 %
601 %    o configure_info:  The configure info.
602 %
603 */
604 MagickExport char *GetConfigureOption(const char *option)
605 {
606   const char
607     *value;
608
609   const ConfigureInfo
610     *configure_info;
611
612   ExceptionInfo
613     *exception;
614
615   assert(option != (const char *) NULL);
616   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",option);
617   exception=AcquireExceptionInfo();
618   configure_info=GetConfigureInfo(option,exception);
619   exception=DestroyExceptionInfo(exception);
620   if (configure_info == (ConfigureInfo *) NULL)
621     return((char *) NULL);
622   value=GetConfigureValue(configure_info);
623   if ((value == (const char *) NULL) || (*value == '\0'))
624     return((char *) NULL);
625   return(ConstantString(value));
626 }
627 \f
628 /*
629 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
630 %                                                                             %
631 %                                                                             %
632 %                                                                             %
633 %  G e t C o n f i g u r e O p t i o n s                                      %
634 %                                                                             %
635 %                                                                             %
636 %                                                                             %
637 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
638 %
639 %  GetConfigureOptions() returns any Magick configuration options associated
640 %  with the specified filename.
641 %
642 %  The format of the GetConfigureOptions method is:
643 %
644 %      LinkedListInfo *GetConfigureOptions(const char *filename,
645 %        ExceptionInfo *exception)
646 %
647 %  A description of each parameter follows:
648 %
649 %    o filename: the configure file name.
650 %
651 %    o exception: return any errors or warnings in this structure.
652 %
653 */
654 MagickExport LinkedListInfo *GetConfigureOptions(const char *filename,
655   ExceptionInfo *exception)
656 {
657   char
658     path[MagickPathExtent];
659
660   const char
661     *element;
662
663   LinkedListInfo
664     *options,
665     *paths;
666
667   StringInfo
668     *xml;
669
670   assert(filename != (const char *) NULL);
671   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
672   assert(exception != (ExceptionInfo *) NULL);
673   (void) CopyMagickString(path,filename,MagickPathExtent);
674   /*
675     Load XML from configuration files to linked-list.
676   */
677   options=NewLinkedList(0);
678   paths=GetConfigurePaths(filename,exception);
679   if (paths != (LinkedListInfo *) NULL)
680     {
681       ResetLinkedListIterator(paths);
682       element=(const char *) GetNextValueInLinkedList(paths);
683       while (element != (const char *) NULL)
684       {
685         (void) FormatLocaleString(path,MagickPathExtent,"%s%s",element,
686           filename);
687         (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
688           "Searching for configure file: \"%s\"",path);
689         xml=ConfigureFileToStringInfo(path);
690         if (xml != (StringInfo *) NULL)
691           (void) AppendValueToLinkedList(options,xml);
692         element=(const char *) GetNextValueInLinkedList(paths);
693       }
694       paths=DestroyLinkedList(paths,RelinquishMagickMemory);
695     }
696 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
697   if (GetNumberOfElementsInLinkedList(options) == 0)
698     {
699       char
700         *blob;
701
702       blob=(char *) NTResourceToBlob(filename);
703       if (blob != (char *) NULL)
704         {
705           xml=AcquireStringInfo(0);
706           SetStringInfoLength(xml,strlen(blob)+1);
707           SetStringInfoDatum(xml,(unsigned char *) blob);
708           SetStringInfoPath(xml,filename);
709           (void) AppendValueToLinkedList(options,xml);
710         }
711     }
712 #endif
713   if (GetNumberOfElementsInLinkedList(options) == 0)
714     (void) ThrowMagickException(exception,GetMagickModule(),ConfigureWarning,
715       "UnableToOpenConfigureFile","`%s'",filename);
716   ResetLinkedListIterator(options);
717   return(options);
718 }
719 \f
720 /*
721 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
722 %                                                                             %
723 %                                                                             %
724 %                                                                             %
725 %  G e t C o n f i g u r e P a t h s                                          %
726 %                                                                             %
727 %                                                                             %
728 %                                                                             %
729 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
730 %
731 %  GetConfigurePaths() returns any Magick configuration paths associated
732 %  with the specified filename.
733 %
734 %  The format of the GetConfigurePaths method is:
735 %
736 %      LinkedListInfo *GetConfigurePaths(const char *filename,
737 %        ExceptionInfo *exception)
738 %
739 %  A description of each parameter follows:
740 %
741 %    o filename: the configure file name.
742 %
743 %    o exception: return any errors or warnings in this structure.
744 %
745 */
746 MagickExport LinkedListInfo *GetConfigurePaths(const char *filename,
747   ExceptionInfo *exception)
748 {
749 #define RegistryKey  "ConfigurePath"
750 #define MagickCoreDLL  "CORE_RL_MagickCore_.dll"
751 #define MagickCoreDebugDLL  "CORE_DB_MagickCore_.dll"
752
753   char
754     path[MagickPathExtent];
755
756   LinkedListInfo
757     *paths;
758
759   assert(filename != (const char *) NULL);
760   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
761   assert(exception != (ExceptionInfo *) NULL);
762   (void) CopyMagickString(path,filename,MagickPathExtent);
763   paths=NewLinkedList(0);
764   {
765     char
766       *configure_path;
767
768     /*
769       Search $MAGICK_CONFIGURE_PATH.
770     */
771     configure_path=GetEnvironmentValue("MAGICK_CONFIGURE_PATH");
772     if (configure_path != (char *) NULL)
773       {
774         register char
775           *p,
776           *q;
777
778         for (p=configure_path-1; p != (char *) NULL; )
779         {
780           (void) CopyMagickString(path,p+1,MagickPathExtent);
781           q=strchr(path,DirectoryListSeparator);
782           if (q != (char *) NULL)
783             *q='\0';
784           q=path+strlen(path)-1;
785           if ((q >= path) && (*q != *DirectorySeparator))
786             (void) ConcatenateMagickString(path,DirectorySeparator,
787               MagickPathExtent);
788           (void) AppendValueToLinkedList(paths,ConstantString(path));
789           p=strchr(p+1,DirectoryListSeparator);
790         }
791         configure_path=DestroyString(configure_path);
792       }
793   }
794 #if defined(MAGICKCORE_INSTALLED_SUPPORT)
795 #if defined(MAGICKCORE_SHARE_PATH)
796   (void) AppendValueToLinkedList(paths,ConstantString(MAGICKCORE_SHARE_PATH));
797 #endif
798 #if defined(MAGICKCORE_SHAREARCH_PATH)
799   (void) AppendValueToLinkedList(paths,ConstantString(
800     MAGICKCORE_SHAREARCH_PATH));
801 #endif
802 #if defined(MAGICKCORE_CONFIGURE_PATH)
803   (void) AppendValueToLinkedList(paths,ConstantString(
804     MAGICKCORE_CONFIGURE_PATH));
805 #endif
806 #if defined(MAGICKCORE_DOCUMENTATION_PATH)
807   (void) AppendValueToLinkedList(paths,ConstantString(
808     MAGICKCORE_DOCUMENTATION_PATH));
809 #endif
810 #if defined(MAGICKCORE_WINDOWS_SUPPORT) && !(defined(MAGICKCORE_CONFIGURE_PATH) || defined(MAGICKCORE_SHARE_PATH))
811   {
812     unsigned char
813       *key_value;
814
815     /*
816       Locate file via registry key.
817     */
818     key_value=NTRegistryKeyLookup(RegistryKey);
819     if (key_value != (unsigned char *) NULL)
820       {
821         (void) FormatLocaleString(path,MagickPathExtent,"%s%s",(char *)
822           key_value,DirectorySeparator);
823         (void) AppendValueToLinkedList(paths,ConstantString(path));
824         key_value=(unsigned char *) RelinquishMagickMemory(key_value);
825       }
826   }
827 #endif
828 #else
829   {
830     char
831       *home;
832
833     /*
834       Search under MAGICK_HOME.
835     */
836     home=GetEnvironmentValue("MAGICK_HOME");
837     if (home != (char *) NULL)
838       {
839 #if !defined(MAGICKCORE_POSIX_SUPPORT) || defined( __VMS )
840         (void) FormatLocaleString(path,MagickPathExtent,"%s%s",home,
841           DirectorySeparator);
842         (void) AppendValueToLinkedList(paths,ConstantString(path));
843 #else
844         (void) FormatLocaleString(path,MagickPathExtent,"%s/etc/%s/",home,
845           MAGICKCORE_CONFIGURE_RELATIVE_PATH);
846         (void) AppendValueToLinkedList(paths,ConstantString(path));
847         (void) FormatLocaleString(path,MagickPathExtent,"%s/share/%s/",home,
848           MAGICKCORE_SHARE_RELATIVE_PATH);
849         (void) AppendValueToLinkedList(paths,ConstantString(path));
850         (void) FormatLocaleString(path,MagickPathExtent,"%s",
851           MAGICKCORE_SHAREARCH_PATH);
852         (void) AppendValueToLinkedList(paths,ConstantString(path));
853 #endif
854         home=DestroyString(home);
855       }
856     }
857   if (*GetClientPath() != '\0')
858     {
859 #if !defined(MAGICKCORE_POSIX_SUPPORT) || defined( __VMS )
860       (void) FormatLocaleString(path,MagickPathExtent,"%s%s",GetClientPath(),
861         DirectorySeparator);
862       (void) AppendValueToLinkedList(paths,ConstantString(path));
863 #else
864       char
865         prefix[MagickPathExtent];
866
867       /*
868         Search based on executable directory if directory is known.
869       */
870       (void) CopyMagickString(prefix,GetClientPath(),MagickPathExtent);
871       ChopPathComponents(prefix,1);
872       (void) FormatLocaleString(path,MagickPathExtent,"%s/etc/%s/",prefix,
873         MAGICKCORE_CONFIGURE_RELATIVE_PATH);
874       (void) AppendValueToLinkedList(paths,ConstantString(path));
875       (void) FormatLocaleString(path,MagickPathExtent,"%s/share/%s/",prefix,
876         MAGICKCORE_SHARE_RELATIVE_PATH);
877       (void) AppendValueToLinkedList(paths,ConstantString(path));
878       (void) FormatLocaleString(path,MagickPathExtent,"%s",
879         MAGICKCORE_SHAREARCH_PATH);
880       (void) AppendValueToLinkedList(paths,ConstantString(path));
881 #endif
882     }
883   /*
884     Search current directory.
885   */
886   (void) AppendValueToLinkedList(paths,ConstantString(""));
887 #endif
888   {
889     char
890       *home;
891
892     home=GetEnvironmentValue("XDG_CONFIG_HOME");
893     if (home == (char *) NULL)
894       home=GetEnvironmentValue("LOCALAPPDATA");
895     if (home == (char *) NULL)
896       home=GetEnvironmentValue("APPDATA");
897     if (home == (char *) NULL)
898       home=GetEnvironmentValue("USERPROFILE");
899     if (home != (char *) NULL)
900       {
901         /*
902           Search $XDG_CONFIG_HOME/ImageMagick.
903         */
904         (void) FormatLocaleString(path,MagickPathExtent,"%s%sImageMagick%s",
905           home,DirectorySeparator,DirectorySeparator);
906         (void) AppendValueToLinkedList(paths,ConstantString(path));
907         home=DestroyString(home);
908       }
909     home=GetEnvironmentValue("HOME");
910     if (home != (char *) NULL)
911       {
912         /*
913           Search $HOME/.config/ImageMagick.
914         */
915         (void) FormatLocaleString(path,MagickPathExtent,
916           "%s%s.config%sImageMagick%s",home,DirectorySeparator,
917           DirectorySeparator,DirectorySeparator);
918         (void) AppendValueToLinkedList(paths,ConstantString(path));
919         home=DestroyString(home);
920       }
921   }
922 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
923   {
924     char
925       module_path[MagickPathExtent];
926
927     if ((NTGetModulePath(MagickCoreDLL,module_path) != MagickFalse) ||
928         (NTGetModulePath(MagickCoreDebugDLL,module_path) != MagickFalse))
929       {
930         unsigned char
931           *key_value;
932
933         /*
934           Search module path.
935         */
936         (void) FormatLocaleString(path,MagickPathExtent,"%s%s",module_path,
937           DirectorySeparator);
938         key_value=NTRegistryKeyLookup(RegistryKey);
939         if (key_value == (unsigned char *) NULL)
940           (void) AppendValueToLinkedList(paths,ConstantString(path));
941         else
942           key_value=(unsigned char *) RelinquishMagickMemory(key_value);
943       }
944     if (NTGetModulePath("Magick.dll",module_path) != MagickFalse)
945       {
946         /*
947           Search PerlMagick module path.
948         */
949         (void) FormatLocaleString(path,MagickPathExtent,"%s%s",module_path,
950           DirectorySeparator);
951         (void) AppendValueToLinkedList(paths,ConstantString(path));
952         (void) FormatLocaleString(path,MagickPathExtent,"%s%s",module_path,
953           "\\inc\\lib\\auto\\Image\\Magick\\");
954         (void) AppendValueToLinkedList(paths,ConstantString(path));
955       }
956   }
957 #endif
958   return(paths);
959 }
960 \f
961 /*
962 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
963 %                                                                             %
964 %                                                                             %
965 %                                                                             %
966 %   G e t C o n f i g u r e V a l u e                                         %
967 %                                                                             %
968 %                                                                             %
969 %                                                                             %
970 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
971 %
972 %  GetConfigureValue() returns the value associated with the configure info.
973 %
974 %  The format of the GetConfigureValue method is:
975 %
976 %      const char *GetConfigureValue(const ConfigureInfo *configure_info)
977 %
978 %  A description of each parameter follows:
979 %
980 %    o configure_info:  The configure info.
981 %
982 */
983 MagickExport const char *GetConfigureValue(const ConfigureInfo *configure_info)
984 {
985   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
986   assert(configure_info != (ConfigureInfo *) NULL);
987   assert(configure_info->signature == MagickCoreSignature);
988   return(configure_info->value);
989 }
990 \f
991 /*
992 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
993 %                                                                             %
994 %                                                                             %
995 %                                                                             %
996 +   I s C o n f i g u r e C a c h e I n s t a n t i a t e d                   %
997 %                                                                             %
998 %                                                                             %
999 %                                                                             %
1000 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1001 %
1002 %  IsConfigureCacheInstantiated() determines if the configure list is
1003 %  instantiated.  If not, it instantiates the list and returns it.
1004 %
1005 %  The format of the IsConfigureInstantiated method is:
1006 %
1007 %      MagickBooleanType IsConfigureCacheInstantiated(ExceptionInfo *exception)
1008 %
1009 %  A description of each parameter follows.
1010 %
1011 %    o exception: return any errors or warnings in this structure.
1012 %
1013 */
1014 static MagickBooleanType IsConfigureCacheInstantiated(ExceptionInfo *exception)
1015 {
1016   if (configure_cache == (LinkedListInfo *) NULL)
1017     {
1018       if (configure_semaphore == (SemaphoreInfo *) NULL)
1019         ActivateSemaphoreInfo(&configure_semaphore);
1020       LockSemaphoreInfo(configure_semaphore);
1021       if (configure_cache == (LinkedListInfo *) NULL)
1022         configure_cache=AcquireConfigureCache(ConfigureFilename,exception);
1023       UnlockSemaphoreInfo(configure_semaphore);
1024     }
1025   return(configure_cache != (LinkedListInfo *) NULL ? MagickTrue : MagickFalse);
1026 }
1027 \f
1028 /*
1029 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1030 %                                                                             %
1031 %                                                                             %
1032 %                                                                             %
1033 %  L i s t C o n f i g u r e I n f o                                          %
1034 %                                                                             %
1035 %                                                                             %
1036 %                                                                             %
1037 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1038 %
1039 %  ListConfigureInfo() lists the configure info to a file.
1040 %
1041 %  The format of the ListConfigureInfo method is:
1042 %
1043 %      MagickBooleanType ListConfigureInfo(FILE *file,ExceptionInfo *exception)
1044 %
1045 %  A description of each parameter follows.
1046 %
1047 %    o file:  An pointer to a FILE.
1048 %
1049 %    o exception: return any errors or warnings in this structure.
1050 %
1051 */
1052 MagickExport MagickBooleanType ListConfigureInfo(FILE *file,
1053   ExceptionInfo *exception)
1054 {
1055   const char
1056     *name,
1057     *path,
1058     *value;
1059
1060   const ConfigureInfo
1061     **configure_info;
1062
1063   register ssize_t
1064     i;
1065
1066   size_t
1067     number_options;
1068
1069   ssize_t
1070     j;
1071
1072   if (file == (const FILE *) NULL)
1073     file=stdout;
1074   configure_info=GetConfigureInfoList("*",&number_options,exception);
1075   if (configure_info == (const ConfigureInfo **) NULL)
1076     return(MagickFalse);
1077   path=(const char *) NULL;
1078   for (i=0; i < (ssize_t) number_options; i++)
1079   {
1080     if (configure_info[i]->stealth != MagickFalse)
1081       continue;
1082     if ((path == (const char *) NULL) ||
1083         (LocaleCompare(path,configure_info[i]->path) != 0))
1084       {
1085         if (configure_info[i]->path != (char *) NULL)
1086           (void) FormatLocaleFile(file,"\nPath: %s\n\n",
1087             configure_info[i]->path);
1088         (void) FormatLocaleFile(file,"Name           Value\n");
1089         (void) FormatLocaleFile(file,
1090           "-------------------------------------------------"
1091           "------------------------------\n");
1092       }
1093     path=configure_info[i]->path;
1094     name="unknown";
1095     if (configure_info[i]->name != (char *) NULL)
1096       name=configure_info[i]->name;
1097     (void) FormatLocaleFile(file,"%s",name);
1098     for (j=(ssize_t) strlen(name); j <= 13; j++)
1099       (void) FormatLocaleFile(file," ");
1100     (void) FormatLocaleFile(file," ");
1101     value="unknown";
1102     if (configure_info[i]->value != (char *) NULL)
1103       value=configure_info[i]->value;
1104     (void) FormatLocaleFile(file,"%s",value);
1105     (void) FormatLocaleFile(file,"\n");
1106   }
1107   (void) fflush(file);
1108   configure_info=(const ConfigureInfo **) RelinquishMagickMemory((void *)
1109     configure_info);
1110   return(MagickTrue);
1111 }
1112 \f
1113 /*
1114 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1115 %                                                                             %
1116 %                                                                             %
1117 %                                                                             %
1118 +   L o a d C o n f i g u r e C a c h e                                       %
1119 %                                                                             %
1120 %                                                                             %
1121 %                                                                             %
1122 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1123 %
1124 %  LoadConfigureCache() loads the configure configurations which provides a
1125 %  mapping between configure attributes and a configure name.
1126 %
1127 %  The format of the LoadConfigureCache method is:
1128 %
1129 %      MagickBooleanType LoadConfigureCache(LinkedListInfo *cache,
1130 %        const char *xml,const char *filename,const size_t depth,
1131 %        ExceptionInfo *exception)
1132 %
1133 %  A description of each parameter follows:
1134 %
1135 %    o xml:  The configure list in XML format.
1136 %
1137 %    o filename:  The configure list filename.
1138 %
1139 %    o depth: depth of <include /> statements.
1140 %
1141 %    o exception: return any errors or warnings in this structure.
1142 %
1143 */
1144 static MagickBooleanType LoadConfigureCache(LinkedListInfo *cache,
1145   const char *xml,const char *filename,const size_t depth,
1146   ExceptionInfo *exception)
1147 {
1148   char
1149     keyword[MagickPathExtent],
1150     *token;
1151
1152   ConfigureInfo
1153     *configure_info;
1154
1155   const char
1156     *q;
1157
1158   MagickStatusType
1159     status;
1160
1161   size_t
1162     extent;
1163
1164   /*
1165     Load the configure map file.
1166   */
1167   (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
1168     "Loading configure file \"%s\" ...",filename);
1169   status=MagickTrue;
1170   configure_info=(ConfigureInfo *) NULL;
1171   token=AcquireString(xml);
1172   extent=strlen(token)+MagickPathExtent;
1173   for (q=(char *) xml; *q != '\0'; )
1174   {
1175     /*
1176       Interpret XML.
1177     */
1178     GetNextToken(q,&q,extent,token);
1179     if (*token == '\0')
1180       break;
1181     (void) CopyMagickString(keyword,token,MagickPathExtent);
1182     if (LocaleNCompare(keyword,"<!DOCTYPE",9) == 0)
1183       {
1184         /*
1185           Doctype element.
1186         */
1187         while ((LocaleNCompare(q,"]>",2) != 0) && (*q != '\0'))
1188           GetNextToken(q,&q,extent,token);
1189         continue;
1190       }
1191     if (LocaleNCompare(keyword,"<!--",4) == 0)
1192       {
1193         /*
1194           Comment element.
1195         */
1196         while ((LocaleNCompare(q,"->",2) != 0) && (*q != '\0'))
1197           GetNextToken(q,&q,extent,token);
1198         continue;
1199       }
1200     if (LocaleCompare(keyword,"<include") == 0)
1201       {
1202         /*
1203           Include element.
1204         */
1205         while (((*token != '/') && (*(token+1) != '>')) && (*q != '\0'))
1206         {
1207           (void) CopyMagickString(keyword,token,MagickPathExtent);
1208           GetNextToken(q,&q,extent,token);
1209           if (*token != '=')
1210             continue;
1211           GetNextToken(q,&q,extent,token);
1212           if (LocaleCompare(keyword,"file") == 0)
1213             {
1214               if (depth > 200)
1215                 (void) ThrowMagickException(exception,GetMagickModule(),
1216                   ConfigureError,"IncludeElementNestedTooDeeply","`%s'",token);
1217               else
1218                 {
1219                   char
1220                     path[MagickPathExtent],
1221                     *file_xml;
1222
1223                   GetPathComponent(filename,HeadPath,path);
1224                   if (*path != '\0')
1225                     (void) ConcatenateMagickString(path,DirectorySeparator,
1226                       MagickPathExtent);
1227                   if (*token == *DirectorySeparator)
1228                     (void) CopyMagickString(path,token,MagickPathExtent);
1229                   else
1230                     (void) ConcatenateMagickString(path,token,MagickPathExtent);
1231                   file_xml=FileToXML(path,~0UL);
1232                   if (file_xml != (char *) NULL)
1233                     {
1234                       status&=LoadConfigureCache(cache,file_xml,path,depth+1,
1235                         exception);
1236                       file_xml=DestroyString(file_xml);
1237                     }
1238                 }
1239             }
1240         }
1241         continue;
1242       }
1243     if (LocaleCompare(keyword,"<configure") == 0)
1244       {
1245         /*
1246           Configure element.
1247         */
1248         configure_info=(ConfigureInfo *) AcquireCriticalMemory(
1249           sizeof(*configure_info));
1250         (void) ResetMagickMemory(configure_info,0,sizeof(*configure_info));
1251         configure_info->path=ConstantString(filename);
1252         configure_info->exempt=MagickFalse;
1253         configure_info->signature=MagickCoreSignature;
1254         continue;
1255       }
1256     if (configure_info == (ConfigureInfo *) NULL)
1257       continue;
1258     if ((LocaleCompare(keyword,"/>") == 0) ||
1259         (LocaleCompare(keyword,"</policy>") == 0))
1260       {
1261         status=AppendValueToLinkedList(cache,configure_info);
1262         if (status == MagickFalse)
1263           (void) ThrowMagickException(exception,GetMagickModule(),
1264             ResourceLimitError,"MemoryAllocationFailed","`%s'",
1265             configure_info->name);
1266         configure_info=(ConfigureInfo *) NULL;
1267         continue;
1268       }
1269     /*
1270       Parse configure element.
1271     */
1272     GetNextToken(q,(const char **) NULL,extent,token);
1273     if (*token != '=')
1274       continue;
1275     GetNextToken(q,&q,extent,token);
1276     GetNextToken(q,&q,extent,token);
1277     switch (*keyword)
1278     {
1279       case 'N':
1280       case 'n':
1281       {
1282         if (LocaleCompare((char *) keyword,"name") == 0)
1283           {
1284             configure_info->name=ConstantString(token);
1285             break;
1286           }
1287         break;
1288       }
1289       case 'S':
1290       case 's':
1291       {
1292         if (LocaleCompare((char *) keyword,"stealth") == 0)
1293           {
1294             configure_info->stealth=IsStringTrue(token);
1295             break;
1296           }
1297         break;
1298       }
1299       case 'V':
1300       case 'v':
1301       {
1302         if (LocaleCompare((char *) keyword,"value") == 0)
1303           {
1304             configure_info->value=ConstantString(token);
1305             break;
1306           }
1307         break;
1308       }
1309       default:
1310         break;
1311     }
1312   }
1313   token=(char *) RelinquishMagickMemory(token);
1314   return(status != 0 ? MagickTrue : MagickFalse);
1315 }