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