]> 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_SHAREARCH_PATH)
676 #if !defined(MAGICKCORE_SHARE_PATH)
677   (void) AppendValueToLinkedList(paths,ConstantString(
678     MAGICKCORE_SHAREARCH_PATH));
679 #else
680   if (LocaleCompare(MAGICKCORE_SHARE_PATH,MAGICKCORE_SHAREARCH_PATH) != 0)
681     (void) AppendValueToLinkedList(paths,ConstantString(
682       MAGICKCORE_SHAREARCH_PATH));
683 #endif
684 #endif
685 #if defined(MAGICKCORE_CONFIGURE_PATH)
686   (void) AppendValueToLinkedList(paths,ConstantString(
687     MAGICKCORE_CONFIGURE_PATH));
688 #endif
689 #if defined(MAGICKCORE_DOCUMENTATION_PATH)
690   (void) AppendValueToLinkedList(paths,ConstantString(
691     MAGICKCORE_DOCUMENTATION_PATH));
692 #endif
693 #if defined(MAGICKCORE_WINDOWS_SUPPORT) && !(defined(MAGICKCORE_CONFIGURE_PATH) || defined(MAGICKCORE_SHARE_PATH))
694   {
695     char
696       *registry_key;
697
698     unsigned char
699       *key_value;
700
701     /*
702       Locate file via registry key.
703     */
704     registry_key="ConfigurePath";
705     key_value=NTRegistryKeyLookup(registry_key);
706     if (key_value != (unsigned char *) NULL)
707       {
708         (void) FormatLocaleString(path,MaxTextExtent,"%s%s",(char *) key_value,
709           DirectorySeparator);
710         (void) AppendValueToLinkedList(paths,ConstantString(path));
711         key_value=(unsigned char *) RelinquishMagickMemory(key_value);
712       }
713   }
714 #endif
715 #else
716   {
717     char
718       *home;
719
720     /*
721       Search under MAGICK_HOME.
722     */
723     home=GetEnvironmentValue("MAGICK_HOME");
724     if (home != (char *) NULL)
725       {
726 #if !defined(MAGICKCORE_POSIX_SUPPORT)
727         (void) FormatLocaleString(path,MaxTextExtent,"%s%s",home,
728           DirectorySeparator);
729         (void) AppendValueToLinkedList(paths,ConstantString(path));
730 #else
731         (void) FormatLocaleString(path,MaxTextExtent,"%s/etc/%s/",home,
732           MAGICKCORE_CONFIGURE_RELATIVE_PATH);
733         (void) AppendValueToLinkedList(paths,ConstantString(path));
734         (void) FormatLocaleString(path,MaxTextExtent,"%s/share/%s/",home,
735           MAGICKCORE_SHARE_RELATIVE_PATH);
736         (void) AppendValueToLinkedList(paths,ConstantString(path));
737 #endif
738         home=DestroyString(home);
739       }
740     }
741   if (*GetClientPath() != '\0')
742     {
743 #if !defined(MAGICKCORE_POSIX_SUPPORT)
744       (void) FormatLocaleString(path,MaxTextExtent,"%s%s",GetClientPath(),
745         DirectorySeparator);
746       (void) AppendValueToLinkedList(paths,ConstantString(path));
747 #else
748       char
749         prefix[MaxTextExtent];
750
751       /*
752         Search based on executable directory if directory is known.
753       */
754       (void) CopyMagickString(prefix,GetClientPath(),MaxTextExtent);
755       ChopPathComponents(prefix,1);
756       (void) FormatLocaleString(path,MaxTextExtent,"%s/etc/%s/",prefix,
757         MAGICKCORE_CONFIGURE_RELATIVE_PATH);
758       (void) AppendValueToLinkedList(paths,ConstantString(path));
759       (void) FormatLocaleString(path,MaxTextExtent,"%s/share/%s/",prefix,
760         MAGICKCORE_SHARE_RELATIVE_PATH);
761       (void) AppendValueToLinkedList(paths,ConstantString(path));
762 #endif
763     }
764   /*
765     Search current directory.
766   */
767   (void) AppendValueToLinkedList(paths,ConstantString(""));
768 #endif
769   {
770     char
771       *home;
772
773     home=GetEnvironmentValue("HOME");
774     if (home == (char *) NULL)
775       home=GetEnvironmentValue("USERPROFILE");
776     if (home != (char *) NULL)
777       {
778         /*
779           Search $HOME/.magick.
780         */
781         (void) FormatLocaleString(path,MaxTextExtent,"%s%s.magick%s",home,
782           DirectorySeparator,DirectorySeparator);
783         (void) AppendValueToLinkedList(paths,ConstantString(path));
784         home=DestroyString(home);
785       }
786   }
787 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
788   {
789     char
790       module_path[MaxTextExtent];
791
792     if ((NTGetModulePath(MagickCoreDLL,module_path) != MagickFalse) ||
793         (NTGetModulePath(MagickCoreDebugDLL,module_path) != MagickFalse))
794       {
795         char
796           *element;
797
798         /*
799           Search module path.
800         */
801         (void) FormatLocaleString(path,MaxTextExtent,"%s%s",module_path,
802           DirectorySeparator);
803         element=(char *) RemoveElementByValueFromLinkedList(paths,path);
804         if (element != (char *) NULL)
805           element=DestroyString(element);
806         (void) AppendValueToLinkedList(paths,ConstantString(path));
807       }
808     if (NTGetModulePath("Magick.dll",module_path) != MagickFalse)
809       {
810         /*
811           Search PerlMagick module path.
812         */
813         (void) FormatLocaleString(path,MaxTextExtent,"%s%s",module_path,
814           DirectorySeparator);
815         (void) AppendValueToLinkedList(paths,ConstantString(path));
816         (void) FormatLocaleString(path,MaxTextExtent,"%s%s",module_path,
817           "\\inc\\lib\\auto\\Image\\Magick\\");
818         (void) AppendValueToLinkedList(paths,ConstantString(path));
819       }
820   }
821 #endif
822   return(paths);
823 }
824 \f
825 /*
826 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
827 %                                                                             %
828 %                                                                             %
829 %                                                                             %
830 %   G e t C o n f i g u r e V a l u e                                         %
831 %                                                                             %
832 %                                                                             %
833 %                                                                             %
834 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
835 %
836 %  GetConfigureValue() returns the value associated with the configure info.
837 %
838 %  The format of the GetConfigureValue method is:
839 %
840 %      const char *GetConfigureValue(const ConfigureInfo *configure_info)
841 %
842 %  A description of each parameter follows:
843 %
844 %    o configure_info:  The configure info.
845 %
846 */
847 MagickExport const char *GetConfigureValue(const ConfigureInfo *configure_info)
848 {
849   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
850   assert(configure_info != (ConfigureInfo *) NULL);
851   assert(configure_info->signature == MagickSignature);
852   return(configure_info->value);
853 }
854 \f
855 /*
856 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
857 %                                                                             %
858 %                                                                             %
859 %                                                                             %
860 +   I n i t i a l i z e C o n f i g u r e L i s t                             %
861 %                                                                             %
862 %                                                                             %
863 %                                                                             %
864 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
865 %
866 %  InitializeConfigureList() initializes the configure list.
867 %
868 %  The format of the InitializeConfigureList method is:
869 %
870 %      MagickBooleanType InitializeConfigureList(ExceptionInfo *exception)
871 %
872 %  A description of each parameter follows.
873 %
874 %    o exception: return any errors or warnings in this structure.
875 %
876 */
877 static MagickBooleanType InitializeConfigureList(ExceptionInfo *exception)
878 {
879   if ((configure_list == (LinkedListInfo *) NULL) &&
880       (instantiate_configure == MagickFalse))
881     {
882       if (configure_semaphore == (SemaphoreInfo *) NULL)
883         AcquireSemaphoreInfo(&configure_semaphore);
884       LockSemaphoreInfo(configure_semaphore);
885       if ((configure_list == (LinkedListInfo *) NULL) &&
886           (instantiate_configure == MagickFalse))
887         {
888           (void) LoadConfigureLists(ConfigureFilename,exception);
889           instantiate_configure=MagickTrue;
890         }
891       UnlockSemaphoreInfo(configure_semaphore);
892     }
893   return(configure_list != (LinkedListInfo *) NULL ? MagickTrue : MagickFalse);
894 }
895 \f
896 /*
897 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
898 %                                                                             %
899 %                                                                             %
900 %                                                                             %
901 %  L i s t C o n f i g u r e I n f o                                          %
902 %                                                                             %
903 %                                                                             %
904 %                                                                             %
905 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
906 %
907 %  ListConfigureInfo() lists the configure info to a file.
908 %
909 %  The format of the ListConfigureInfo method is:
910 %
911 %      MagickBooleanType ListConfigureInfo(FILE *file,ExceptionInfo *exception)
912 %
913 %  A description of each parameter follows.
914 %
915 %    o file:  An pointer to a FILE.
916 %
917 %    o exception: return any errors or warnings in this structure.
918 %
919 */
920 MagickExport MagickBooleanType ListConfigureInfo(FILE *file,
921   ExceptionInfo *exception)
922 {
923   const char
924     *name,
925     *path,
926     *value;
927
928   const ConfigureInfo
929     **configure_info;
930
931   register ssize_t
932     i;
933
934   size_t
935     number_options;
936
937   ssize_t
938     j;
939
940   if (file == (const FILE *) NULL)
941     file=stdout;
942   configure_info=GetConfigureInfoList("*",&number_options,exception);
943   if (configure_info == (const ConfigureInfo **) NULL)
944     return(MagickFalse);
945   path=(const char *) NULL;
946   for (i=0; i < (ssize_t) number_options; i++)
947   {
948     if (configure_info[i]->stealth != MagickFalse)
949       continue;
950     if ((path == (const char *) NULL) ||
951         (LocaleCompare(path,configure_info[i]->path) != 0))
952       {
953         if (configure_info[i]->path != (char *) NULL)
954           (void) FormatLocaleFile(file,"\nPath: %s\n\n",
955             configure_info[i]->path);
956         (void) FormatLocaleFile(file,"Name          Value\n");
957         (void) FormatLocaleFile(file,
958           "-------------------------------------------------"
959           "------------------------------\n");
960       }
961     path=configure_info[i]->path;
962     name="unknown";
963     if (configure_info[i]->name != (char *) NULL)
964       name=configure_info[i]->name;
965     (void) FormatLocaleFile(file,"%s",name);
966     for (j=(ssize_t) strlen(name); j <= 12; j++)
967       (void) FormatLocaleFile(file," ");
968     (void) FormatLocaleFile(file," ");
969     value="unknown";
970     if (configure_info[i]->value != (char *) NULL)
971       value=configure_info[i]->value;
972     (void) FormatLocaleFile(file,"%s",value);
973     (void) FormatLocaleFile(file,"\n");
974   }
975   (void) fflush(file);
976   configure_info=(const ConfigureInfo **)
977     RelinquishMagickMemory((void *) configure_info);
978   return(MagickTrue);
979 }
980 \f
981 /*
982 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
983 %                                                                             %
984 %                                                                             %
985 %                                                                             %
986 +   L o a d C o n f i g u r e L i s t                                         %
987 %                                                                             %
988 %                                                                             %
989 %                                                                             %
990 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
991 %
992 %  LoadConfigureList() loads the configure configuration file which provides a
993 %  mapping between configure attributes and a configure name.
994 %
995 %  The format of the LoadConfigureList method is:
996 %
997 %      MagickBooleanType LoadConfigureList(const char *xml,const char *filename,
998 %        const size_t depth,ExceptionInfo *exception)
999 %
1000 %  A description of each parameter follows:
1001 %
1002 %    o xml:  The configure list in XML format.
1003 %
1004 %    o filename:  The configure list filename.
1005 %
1006 %    o depth: depth of <include /> statements.
1007 %
1008 %    o exception: return any errors or warnings in this structure.
1009 %
1010 */
1011 static MagickBooleanType LoadConfigureList(const char *xml,const char *filename,
1012   const size_t depth,ExceptionInfo *exception)
1013 {
1014   char
1015     keyword[MaxTextExtent],
1016     *token;
1017
1018   ConfigureInfo
1019     *configure_info;
1020
1021   const char
1022     *q;
1023
1024   MagickBooleanType
1025     status;
1026
1027   /*
1028     Load the configure map file.
1029   */
1030   (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
1031     "Loading configure file \"%s\" ...",filename);
1032   if (configure_list == (LinkedListInfo *) NULL)
1033     {
1034       configure_list=NewLinkedList(0);
1035       if (configure_list == (LinkedListInfo *) NULL)
1036         {
1037           ThrowFileException(exception,ResourceLimitError,
1038             "MemoryAllocationFailed",filename);
1039           return(MagickFalse);
1040         }
1041     }
1042   status=MagickTrue;
1043   configure_info=(ConfigureInfo *) NULL;
1044   token=AcquireString((char *) xml);
1045   for (q=(char *) xml; *q != '\0'; )
1046   {
1047     /*
1048       Interpret XML.
1049     */
1050     GetMagickToken(q,&q,token);
1051     if (*token == '\0')
1052       break;
1053     (void) CopyMagickString(keyword,token,MaxTextExtent);
1054     if (LocaleNCompare(keyword,"<!DOCTYPE",9) == 0)
1055       {
1056         /*
1057           Doctype element.
1058         */
1059         while ((LocaleNCompare(q,"]>",2) != 0) && (*q != '\0'))
1060           GetMagickToken(q,&q,token);
1061         continue;
1062       }
1063     if (LocaleNCompare(keyword,"<!--",4) == 0)
1064       {
1065         /*
1066           Comment element.
1067         */
1068         while ((LocaleNCompare(q,"->",2) != 0) && (*q != '\0'))
1069           GetMagickToken(q,&q,token);
1070         continue;
1071       }
1072     if (LocaleCompare(keyword,"<include") == 0)
1073       {
1074         /*
1075           Include element.
1076         */
1077         while (((*token != '/') && (*(token+1) != '>')) && (*q != '\0'))
1078         {
1079           (void) CopyMagickString(keyword,token,MaxTextExtent);
1080           GetMagickToken(q,&q,token);
1081           if (*token != '=')
1082             continue;
1083           GetMagickToken(q,&q,token);
1084           if (LocaleCompare(keyword,"file") == 0)
1085             {
1086               if (depth > 200)
1087                 (void) ThrowMagickException(exception,GetMagickModule(),
1088                   ConfigureError,"IncludeElementNestedTooDeeply","`%s'",token);
1089               else
1090                 {
1091                   char
1092                     path[MaxTextExtent],
1093                     *xml;
1094
1095                   GetPathComponent(filename,HeadPath,path);
1096                   if (*path != '\0')
1097                     (void) ConcatenateMagickString(path,DirectorySeparator,
1098                       MaxTextExtent);
1099                   if (*token == *DirectorySeparator)
1100                     (void) CopyMagickString(path,token,MaxTextExtent);
1101                   else
1102                     (void) ConcatenateMagickString(path,token,MaxTextExtent);
1103                   xml=FileToString(path,~0,exception);
1104                   if (xml != (char *) NULL)
1105                     {
1106                       status=LoadConfigureList(xml,path,depth+1,exception);
1107                       xml=(char *) RelinquishMagickMemory(xml);
1108                     }
1109                 }
1110             }
1111         }
1112         continue;
1113       }
1114     if (LocaleCompare(keyword,"<configure") == 0)
1115       {
1116         /*
1117           Configure element.
1118         */
1119         configure_info=(ConfigureInfo *) AcquireMagickMemory(
1120           sizeof(*configure_info));
1121         if (configure_info == (ConfigureInfo *) NULL)
1122           ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1123         (void) ResetMagickMemory(configure_info,0,sizeof(*configure_info));
1124         configure_info->path=ConstantString(filename);
1125         configure_info->exempt=MagickFalse;
1126         configure_info->signature=MagickSignature;
1127         continue;
1128       }
1129     if (configure_info == (ConfigureInfo *) NULL)
1130       continue;
1131     if (LocaleCompare(keyword,"/>") == 0)
1132       {
1133         status=AppendValueToLinkedList(configure_list,configure_info);
1134         if (status == MagickFalse)
1135           (void) ThrowMagickException(exception,GetMagickModule(),
1136             ResourceLimitError,"MemoryAllocationFailed","`%s'",
1137             configure_info->name);
1138         configure_info=(ConfigureInfo *) NULL;
1139       }
1140     /*
1141       Parse configure element.
1142     */
1143     GetMagickToken(q,(const char **) NULL,token);
1144     if (*token != '=')
1145       continue;
1146     GetMagickToken(q,&q,token);
1147     GetMagickToken(q,&q,token);
1148     switch (*keyword)
1149     {
1150       case 'N':
1151       case 'n':
1152       {
1153         if (LocaleCompare((char *) keyword,"name") == 0)
1154           {
1155             configure_info->name=ConstantString(token);
1156             break;
1157           }
1158         break;
1159       }
1160       case 'S':
1161       case 's':
1162       {
1163         if (LocaleCompare((char *) keyword,"stealth") == 0)
1164           {
1165             configure_info->stealth=IsMagickTrue(token);
1166             break;
1167           }
1168         break;
1169       }
1170       case 'V':
1171       case 'v':
1172       {
1173         if (LocaleCompare((char *) keyword,"value") == 0)
1174           {
1175             configure_info->value=ConstantString(token);
1176             break;
1177           }
1178         break;
1179       }
1180       default:
1181         break;
1182     }
1183   }
1184   token=(char *) RelinquishMagickMemory(token);
1185   return(status);
1186 }
1187 \f
1188 /*
1189 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1190 %                                                                             %
1191 %                                                                             %
1192 %                                                                             %
1193 %  L o a d C o n f i g u r e L i s t s                                        %
1194 %                                                                             %
1195 %                                                                             %
1196 %                                                                             %
1197 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1198 %
1199 %  LoadConfigureList() loads one or more configure configuration files which
1200 %  provides a mapping between configure attributes and a configure name.
1201 %
1202 %  The format of the LoadConfigureLists method is:
1203 %
1204 %      MagickBooleanType LoadConfigureLists(const char *filename,
1205 %        ExceptionInfo *exception)
1206 %
1207 %  A description of each parameter follows:
1208 %
1209 %    o filename: the font file name.
1210 %
1211 %    o exception: return any errors or warnings in this structure.
1212 %
1213 */
1214 static MagickBooleanType LoadConfigureLists(const char *filename,
1215   ExceptionInfo *exception)
1216 {
1217   const StringInfo
1218     *option;
1219
1220   LinkedListInfo
1221     *options;
1222
1223   MagickStatusType
1224     status;
1225
1226   register ssize_t
1227     i;
1228
1229   /*
1230     Load built-in configure map.
1231   */
1232   status=MagickFalse;
1233   if (configure_list == (LinkedListInfo *) NULL)
1234     {
1235       configure_list=NewLinkedList(0);
1236       if (configure_list == (LinkedListInfo *) NULL)
1237         {
1238           ThrowFileException(exception,ResourceLimitError,
1239             "MemoryAllocationFailed",filename);
1240           return(MagickFalse);
1241         }
1242     }
1243   for (i=0; i < (ssize_t) (sizeof(ConfigureMap)/sizeof(*ConfigureMap)); i++)
1244   {
1245     ConfigureInfo
1246       *configure_info;
1247
1248     register const ConfigureMapInfo
1249       *p;
1250
1251     p=ConfigureMap+i;
1252     configure_info=(ConfigureInfo *) AcquireMagickMemory(
1253       sizeof(*configure_info));
1254     if (configure_info == (ConfigureInfo *) NULL)
1255       {
1256         (void) ThrowMagickException(exception,GetMagickModule(),
1257           ResourceLimitError,"MemoryAllocationFailed","`%s'",
1258           configure_info->name);
1259         continue;
1260       }
1261     (void) ResetMagickMemory(configure_info,0,sizeof(*configure_info));
1262     configure_info->path=(char *) "[built-in]";
1263     configure_info->name=(char *) p->name;
1264     configure_info->value=(char *) p->value;
1265     configure_info->exempt=MagickTrue;
1266     configure_info->signature=MagickSignature;
1267     status=AppendValueToLinkedList(configure_list,configure_info);
1268     if (status == MagickFalse)
1269       (void) ThrowMagickException(exception,GetMagickModule(),
1270         ResourceLimitError,"MemoryAllocationFailed","`%s'",
1271         configure_info->name);
1272   }
1273   /*
1274     Load external configure map.
1275   */
1276   options=GetConfigureOptions(filename,exception);
1277   option=(const StringInfo *) GetNextValueInLinkedList(options);
1278   while (option != (const StringInfo *) NULL)
1279   {
1280     status|=LoadConfigureList((const char *) GetStringInfoDatum(option),
1281       GetStringInfoPath(option),0,exception);
1282     option=(const StringInfo *) GetNextValueInLinkedList(options);
1283   }
1284   options=DestroyConfigureOptions(options);
1285   return(status != 0 ? MagickTrue : MagickFalse);
1286 }