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