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