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